diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bcbd0d6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3 +MAINTAINER Ameya Lokare + +ENV PYTHONUNBUFFERED 1 +RUN mkdir -p /opt/services/flaskapp/src +#VOLUME ["/opt/services/flaskapp/src"] +# We copy the requirements.txt file first to avoid cache invalidations +COPY requirements.txt /opt/services/flaskapp/src/ +WORKDIR /opt/services/flaskapp/src +RUN pip install -r requirements.txt +COPY . /opt/services/flaskapp/src +EXPOSE 5090 +CMD ["python", "app.py"] diff --git a/app.py b/app.py new file mode 100644 index 0000000..a19530b --- /dev/null +++ b/app.py @@ -0,0 +1,28 @@ +import datetime +import os + +from flask import Flask, render_template, redirect, url_for +from forms import SignupForm + +from models import Signups +from database import db_session + +app = Flask(__name__) +app.secret_key = os.environ['APP_SECRET_KEY'] + +@app.route("/", methods=('GET', 'POST')) +def signup(): + form = SignupForm() + if form.validate_on_submit(): + signup = Signups(name=form.name.data, email=form.email.data, date_signed_up=datetime.datetime.now()) + db_session.add(signup) + db_session.commit() + return redirect(url_for('success')) + return render_template('signup.html', form=form) + +@app.route("/success") +def success(): + return "Thank you for signing up!" + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5090, debug=True) diff --git a/conf.d/flaskapp.conf b/conf.d/flaskapp.conf new file mode 100644 index 0000000..66f2803 --- /dev/null +++ b/conf.d/flaskapp.conf @@ -0,0 +1,14 @@ +server { + listen 80; + server_name localhost; + + location / { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + + proxy_pass http://flaskapp:5090; + } +} diff --git a/database.py b/database.py new file mode 100644 index 0000000..b3aa493 --- /dev/null +++ b/database.py @@ -0,0 +1,24 @@ +import os +from sqlalchemy import create_engine +from sqlalchemy.orm import scoped_session, sessionmaker +from sqlalchemy.ext.declarative import declarative_base + +user = os.environ['POSTGRES_USER'] +pwd = os.environ['POSTGRES_PASSWORD'] +db = os.environ['POSTGRES_DB'] +host = 'db' +port = '5432' +engine = create_engine('postgres://%s:%s@%s:%s/%s' % (user, pwd, host, port, db)) + +db_session = scoped_session(sessionmaker(autocommit=False, + autoflush=False, + bind=engine)) +Base = declarative_base() +Base.query = db_session.query_property() + +def init_db(): + # import all modules here that might define models so that + # they will be registered properly on the metadata. Otherwise + # you will have to import them first before calling init_db() + import models + Base.metadata.create_all(bind=engine) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..917b4f6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: '3' +services: + db: + image: "postgres:9.6.5" + volumes: + - "dbdata:/var/lib/postgresql/data" + env_file: + - env_file + networks: + - db_nw + flaskapp: + build: . + env_file: + - env_file + volumes: + - .:/opt/services/flaskapp/src + networks: + - db_nw + - web_nw + depends_on: + - db + nginx: + image: "nginx:1.13.5" + ports: + - "8080:80" + volumes: + - ./conf.d:/etc/nginx/conf.d + networks: + - web_nw + depends_on: + - flaskapp +networks: + db_nw: + driver: bridge + web_nw: + driver: bridge +volumes: + dbdata: \ No newline at end of file diff --git a/env_file b/env_file new file mode 100644 index 0000000..eb6db26 --- /dev/null +++ b/env_file @@ -0,0 +1,4 @@ +POSTGRES_USER=postgres +POSTGRES_PASSWORD=USE_YOUR_PASSWORD +POSTGRES_DB=flaskapp_db +APP_SECRET_KEY=USE_YOUR_SECRET_KEY diff --git a/forms.py b/forms.py new file mode 100644 index 0000000..026a000 --- /dev/null +++ b/forms.py @@ -0,0 +1,8 @@ +from flask_wtf import FlaskForm +from wtforms import StringField +from wtforms.validators import DataRequired + +class SignupForm(FlaskForm): + name = StringField('name', validators=[DataRequired()]) + email = StringField('email', validators=[DataRequired()]) + diff --git a/models.py b/models.py new file mode 100644 index 0000000..2a34299 --- /dev/null +++ b/models.py @@ -0,0 +1,13 @@ +from database import Base +from sqlalchemy import Column, Integer, String +from sqlalchemy.types import DateTime + +class Signups(Base): + """ + Example Signups table + """ + __tablename__ = 'signups' + id = Column(Integer, primary_key=True) + name = Column(String(256)) + email = Column(String(256), unique=True) + date_signed_up = Column(DateTime()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d872414 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask +psycopg2 +SQLAlchemy +Flask-WTF diff --git a/templates/signup.html b/templates/signup.html new file mode 100644 index 0000000..8cdd5b4 --- /dev/null +++ b/templates/signup.html @@ -0,0 +1,12 @@ + + + +

Hello, please sign up!

+
+ {{ form.csrf_token }} + {{ form.name.label }} {{ form.name(size=20) }} + {{ form.email.label }} {{ form.email(size=20) }} + +
+ +