Skip to content

Commit 7bba110

Browse files
committed
Full example of nginx+flask+postgres multi-container setup
0 parents  commit 7bba110

11 files changed

+159
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__pycache__

Dockerfile

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM python:3
2+
MAINTAINER Ameya Lokare <[email protected]>
3+
4+
ENV PYTHONUNBUFFERED 1
5+
RUN mkdir -p /opt/services/flaskapp/src
6+
#VOLUME ["/opt/services/flaskapp/src"]
7+
# We copy the requirements.txt file first to avoid cache invalidations
8+
COPY requirements.txt /opt/services/flaskapp/src/
9+
WORKDIR /opt/services/flaskapp/src
10+
RUN pip install -r requirements.txt
11+
COPY . /opt/services/flaskapp/src
12+
EXPOSE 5090
13+
CMD ["python", "app.py"]

app.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import datetime
2+
import os
3+
4+
from flask import Flask, render_template, redirect, url_for
5+
from forms import SignupForm
6+
7+
from models import Signups
8+
from database import db_session
9+
10+
app = Flask(__name__)
11+
app.secret_key = os.environ['APP_SECRET_KEY']
12+
13+
@app.route("/", methods=('GET', 'POST'))
14+
def signup():
15+
form = SignupForm()
16+
if form.validate_on_submit():
17+
signup = Signups(name=form.name.data, email=form.email.data, date_signed_up=datetime.datetime.now())
18+
db_session.add(signup)
19+
db_session.commit()
20+
return redirect(url_for('success'))
21+
return render_template('signup.html', form=form)
22+
23+
@app.route("/success")
24+
def success():
25+
return "Thank you for signing up!"
26+
27+
if __name__ == '__main__':
28+
app.run(host='0.0.0.0', port=5090, debug=True)

conf.d/flaskapp.conf

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
server {
2+
listen 80;
3+
server_name localhost;
4+
5+
location / {
6+
proxy_set_header Host $host;
7+
proxy_set_header X-Real-IP $remote_addr;
8+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9+
proxy_set_header X-Forwarded-Proto $scheme;
10+
proxy_set_header Host $http_host;
11+
12+
proxy_pass http://flaskapp:5090;
13+
}
14+
}

database.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import os
2+
from sqlalchemy import create_engine
3+
from sqlalchemy.orm import scoped_session, sessionmaker
4+
from sqlalchemy.ext.declarative import declarative_base
5+
6+
user = os.environ['POSTGRES_USER']
7+
pwd = os.environ['POSTGRES_PASSWORD']
8+
db = os.environ['POSTGRES_DB']
9+
host = 'db'
10+
port = '5432'
11+
engine = create_engine('postgres://%s:%s@%s:%s/%s' % (user, pwd, host, port, db))
12+
13+
db_session = scoped_session(sessionmaker(autocommit=False,
14+
autoflush=False,
15+
bind=engine))
16+
Base = declarative_base()
17+
Base.query = db_session.query_property()
18+
19+
def init_db():
20+
# import all modules here that might define models so that
21+
# they will be registered properly on the metadata. Otherwise
22+
# you will have to import them first before calling init_db()
23+
import models
24+
Base.metadata.create_all(bind=engine)

docker-compose.yml

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
version: '3'
2+
services:
3+
db:
4+
image: "postgres:9.6.5"
5+
volumes:
6+
- "dbdata:/var/lib/postgresql/data"
7+
env_file:
8+
- env_file
9+
networks:
10+
- db_nw
11+
flaskapp:
12+
build: .
13+
env_file:
14+
- env_file
15+
volumes:
16+
- .:/opt/services/flaskapp/src
17+
networks:
18+
- db_nw
19+
- web_nw
20+
depends_on:
21+
- db
22+
nginx:
23+
image: "nginx:1.13.5"
24+
ports:
25+
- "8080:80"
26+
volumes:
27+
- ./conf.d:/etc/nginx/conf.d
28+
networks:
29+
- web_nw
30+
depends_on:
31+
- flaskapp
32+
networks:
33+
db_nw:
34+
driver: bridge
35+
web_nw:
36+
driver: bridge
37+
volumes:
38+
dbdata:

env_file

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
POSTGRES_USER=postgres
2+
POSTGRES_PASSWORD=USE_YOUR_PASSWORD
3+
POSTGRES_DB=flaskapp_db
4+
APP_SECRET_KEY=USE_YOUR_SECRET_KEY

forms.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from flask_wtf import FlaskForm
2+
from wtforms import StringField
3+
from wtforms.validators import DataRequired
4+
5+
class SignupForm(FlaskForm):
6+
name = StringField('name', validators=[DataRequired()])
7+
email = StringField('email', validators=[DataRequired()])
8+

models.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from database import Base
2+
from sqlalchemy import Column, Integer, String
3+
from sqlalchemy.types import DateTime
4+
5+
class Signups(Base):
6+
"""
7+
Example Signups table
8+
"""
9+
__tablename__ = 'signups'
10+
id = Column(Integer, primary_key=True)
11+
name = Column(String(256))
12+
email = Column(String(256), unique=True)
13+
date_signed_up = Column(DateTime())

requirements.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Flask
2+
psycopg2
3+
SQLAlchemy
4+
Flask-WTF

templates/signup.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<body>
4+
<h1> Hello, please sign up! </h1>
5+
<form method="POST" action="/">
6+
{{ form.csrf_token }}
7+
{{ form.name.label }} {{ form.name(size=20) }}
8+
{{ form.email.label }} {{ form.email(size=20) }}
9+
<input type="submit" value="Go">
10+
</form>
11+
</body>
12+
</html>

0 commit comments

Comments
 (0)