From 0475a145f42930ba9cc00bc8b59e5b8f33f49815 Mon Sep 17 00:00:00 2001 From: Michael Herman Date: Sat, 23 Jun 2018 17:41:29 -0600 Subject: [PATCH] init --- Dockerfile | 47 +++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + docker-compose.yml | 24 ++++++++++++++++++++++ manage.py | 28 ++++++++++++++++++++++++++ project/__init__.py | 32 +++++++++++++++++++++++++++++ project/api/models.py | 25 +++++++++++++++++++++++ project/api/users.py | 28 ++++++++++++++++++++++++++ project/config.py | 7 +++++++ project/db/Dockerfile | 4 ++++ project/db/create.sql | 1 + requirements.txt | 5 +++++ 11 files changed, 202 insertions(+) create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml create mode 100644 manage.py create mode 100644 project/__init__.py create mode 100644 project/api/models.py create mode 100644 project/api/users.py create mode 100644 project/config.py create mode 100644 project/db/Dockerfile create mode 100644 project/db/create.sql create mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..51b42b5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +########### +# BUILDER # +########### + +# Base Image +FROM python:3.6 as builder + +# Install Requirements +COPY requirements.txt / +RUN pip wheel --no-cache-dir --no-deps --wheel-dir /wheels -r requirements.txt + + +######### +# FINAL # +######### + +# Base Image +FROM python:3.6-slim + +# Create directory for the app user +RUN mkdir -p /home/app + +# Create the app user +RUN groupadd app && useradd -g app app + +# Create the home directory +ENV HOME=/home/app +ENV APP_HOME=/home/app/web +RUN mkdir $APP_HOME +WORKDIR $APP_HOME + +# Install Requirements +COPY --from=builder /wheels /wheels +COPY --from=builder requirements.txt . +RUN pip install --no-cache /wheels/* + +# Copy in the Flask code +COPY . $APP_HOME + +# Chown all the files to the app user +RUN chown -R app:app $APP_HOME + +# Change to the app user +USER app + +# run server +CMD gunicorn -b 0.0.0.0:5000 manage:app diff --git a/README.md b/README.md new file mode 100644 index 0000000..dc2c3c5 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Running Flask on Docker Swarm diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8fd35a3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +version: '3.6' + +services: + + web: + build: . + ports: + - 5001:5000 + environment: + - FLASK_ENV=production + - APP_SETTINGS=project.config.DevelopmentConfig + - DATABASE_URL=postgres://postgres:postgres@db:5432/users + depends_on: + - db + + db: + build: + context: ./project/db + dockerfile: Dockerfile + expose: + - 5432 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..92c034d --- /dev/null +++ b/manage.py @@ -0,0 +1,28 @@ +from flask.cli import FlaskGroup + +from project import create_app, db +from project.api.models import User + +app = create_app() +cli = FlaskGroup(create_app=create_app) + + +@cli.command() +def recreate_db(): + db.drop_all() + db.create_all() + db.session.commit() + + +@cli.command() +def seed_db(): + """Seeds the database.""" + db.session.add(User( + username='michael', + email='michael@notreal.com', + )) + db.session.commit() + + +if __name__ == '__main__': + cli() diff --git a/project/__init__.py b/project/__init__.py new file mode 100644 index 0000000..b0f504f --- /dev/null +++ b/project/__init__.py @@ -0,0 +1,32 @@ +import os + +from flask import Flask +from flask_sqlalchemy import SQLAlchemy +from flask_migrate import Migrate + + +# instantiate the extensions +db = SQLAlchemy() +migrate = Migrate() + + +def create_app(script_info=None): + + # instantiate the app + app = Flask(__name__) + + # set config + app_settings = os.getenv('APP_SETTINGS') + app.config.from_object(app_settings) + + # set up extensions + db.init_app(app) + migrate.init_app(app, db) + + # register blueprints + from project.api.users import users_blueprint + app.register_blueprint(users_blueprint) + + # shell context for flask cli + app.shell_context_processor({'app': app, 'db': db}) + return app diff --git a/project/api/models.py b/project/api/models.py new file mode 100644 index 0000000..a38d8be --- /dev/null +++ b/project/api/models.py @@ -0,0 +1,25 @@ +from flask import current_app + +from project import db + + +class User(db.Model): + __tablename__ = "users" + id = db.Column(db.Integer, primary_key=True, autoincrement=True) + username = db.Column(db.String(128), unique=True, nullable=False) + email = db.Column(db.String(128), unique=True, nullable=False) + active = db.Column(db.Boolean, default=True, nullable=False) + admin = db.Column(db.Boolean, default=False, nullable=False) + + def __init__(self, username, email): + self.username = username + self.email = email + + def to_json(self): + return { + 'id': self.id, + 'username': self.username, + 'email': self.email, + 'active': self.active, + 'admin': self.admin + } diff --git a/project/api/users.py b/project/api/users.py new file mode 100644 index 0000000..fcba225 --- /dev/null +++ b/project/api/users.py @@ -0,0 +1,28 @@ +import os + +from flask import Blueprint, jsonify, request + +from project.api.models import User + + +users_blueprint = Blueprint('users', __name__, template_folder='./templates') + + +@users_blueprint.route('/users/ping', methods=['GET']) +def ping_pong(): + return jsonify({ + 'status': 'success', + 'message': 'pong!', + 'container_id': os.uname()[1] + }) + + +@users_blueprint.route('/users', methods=['GET']) +def get_all_users(): + """Get all users""" + response_object = { + 'status': 'success', + 'users': [user.to_json() for user in User.query.all()], + 'container_id': os.uname()[1] + } + return jsonify(response_object), 200 diff --git a/project/config.py b/project/config.py new file mode 100644 index 0000000..542334c --- /dev/null +++ b/project/config.py @@ -0,0 +1,7 @@ +import os + + +class DevelopmentConfig(): + """Development configuration""" + SQLALCHEMY_TRACK_MODIFICATIONS = False + SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') diff --git a/project/db/Dockerfile b/project/db/Dockerfile new file mode 100644 index 0000000..3a145f0 --- /dev/null +++ b/project/db/Dockerfile @@ -0,0 +1,4 @@ +FROM postgres:10.4-alpine + +# run create.sql on init +ADD create.sql /docker-entrypoint-initdb.d diff --git a/project/db/create.sql b/project/db/create.sql new file mode 100644 index 0000000..d6f3b34 --- /dev/null +++ b/project/db/create.sql @@ -0,0 +1 @@ +CREATE DATABASE users; diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1de783b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +Flask==1.0.2 +Flask-SQLAlchemy==2.3.2 +flask-migrate==2.1.1 +gunicorn==19.8.1 +psycopg2==2.7.3.2