Skip to content

Commit

Permalink
Docker updates and environment variables
Browse files Browse the repository at this point in the history
  • Loading branch information
nickjj committed Apr 9, 2019
1 parent f1a1ebb commit 0f9eee3
Show file tree
Hide file tree
Showing 23 changed files with 170 additions and 56 deletions.
2 changes: 0 additions & 2 deletions .env

This file was deleted.

68 changes: 68 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Commented out values are what the application sets as a default. You don't
# need to set them unless you plan to override their default values.

COMPOSE_PROJECT_NAME=snakeeyes

# Which Celery backend server should you connect to?
#CELERY_BROKER_URL=redis://redis:6379/0

# In development, having bytecode laying around can cause all sorts of weird
# issues with Docker. These are *.pyc file and the __pycache__/ folder.
PYTHONDONTWRITEBYTECODE=true

# Which environment is running? This should be "development" or "production".
FLASK_ENV=development

# You should generate a random string of 64+ characters for this value in prod.
SECRET_KEY=insecure_key_for_dev

# What mail server should you connect to?
#MAIL_SERVER=smtp.gmail.com
#MAIL_PORT=587
#MAIL_USE_TLS=true
#MAIL_USE_SSL=false
MAIL_USERNAME=
MAIL_PASSWORD=
#MAIL_DEFAULT_SENDER=contact@local.host

# With Docker for Windows / Mac / Linux then this default value should work.
# If you have Docker running in a VM, put the VM's IP address here instead.
#SERVER_NAME=localhost:8000

# Do you want code reloading to work with your app server? Don't do this in
# production (it's turned off by default, so don't worry about it).
WEB_RELOAD=true

# Which address and port should gunicorn bind to?
#WEB_BIND=0.0.0.0:8000

# How many workers and threads should your app use?
WEB_CONCURRENCY=1
#PYTHON_MAX_THREADS=1

# Should Docker restart your containers if they go down?
DOCKER_RESTART_POLICY=no

# What healthcheck test command do you want to run? In development, having it
# curl your web server will result in a lot of log spam, so setting it to
# /bin/true is an easy way to make the healthcheck do basically nothing.
DOCKER_HEALTHCHECK_TEST=/bin/true

# How long should Docker wait before it SIGKILLs your process?
#DOCKER_STOP_GRACE_PERIOD=3s

# What port should be published back to the Docker host for your app server?
DOCKER_WEB_PORT=8000

# What volume path should be used?
DOCKER_WEB_VOLUME=.:/app

# What port should be published back to the Docker host? Be careful with using
# 0.0.0.0 or no host on the left because then anyone will be able to attempt to
# log in to your PostgreSQL server since the port would be publicly accessible.
#
# If you're using Docker for Windows / Mac, it's safe to keep it as is and you
# will be able to connect to PostgreSQL with external tools like pgadmin.
# Change this to your VM's IP address if you're using the Docker Toolbox.
#DOCKER_POSTGRES_PORT=127.0.0.1:5432:5432

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ docs/_build/
tmtags

# App ignores.
.env
celerybeat*
instance/settings.py

27 changes: 21 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
FROM python:2.7-slim
FROM python:2.7.15-slim-stretch
LABEL maintainer="Nick Janetakis <nick.janetakis@gmail.com>"

RUN apt-get update && apt-get install -qq -y \
build-essential libpq-dev --no-install-recommends

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

ENV BUILD_DEPS="build-essential" \
APP_DEPS="curl libpq-dev"

RUN apt-get update \
&& apt-get install -y ${BUILD_DEPS} ${APP_DEPS} --no-install-recommends \
&& pip install -r requirements.txt \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /usr/share/doc && rm -rf /usr/share/man \
&& apt-get purge -y --auto-remove ${BUILD_DEPS} \
&& apt-get clean

ARG FLASK_ENV="production"
ENV FLASK_ENV="${FLASK_ENV}" \
PYTHONUNBUFFERED="true"

COPY . .

RUN pip install --editable .

CMD gunicorn -b 0.0.0.0:8000 --access-logfile - "snakeeyes.app:create_app()"
EXPOSE 8000

CMD ["gunicorn", "-c", "python:config.gunicorn", "snakeeyes.app:create_app()"]

16 changes: 16 additions & 0 deletions config/gunicorn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-

import multiprocessing
import os

from distutils.util import strtobool


bind = os.getenv('WEB_BIND', '0.0.0.0:8000')
accesslog = '-'
access_log_format = "%(h)s %(l)s %(u)s %(t)s '%(r)s' %(s)s %(b)s '%(f)s' '%(a)s' in %(D)sµs"

workers = int(os.getenv('WEB_CONCURRENCY', multiprocessing.cpu_count() * 2))
threads = int(os.getenv('PYTHON_MAX_THREADS', 1))

reload = bool(strtobool(os.getenv('WEB_RELOAD', 'false')))
29 changes: 17 additions & 12 deletions config/settings.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
DEBUG = True
import os
from distutils.util import strtobool

SERVER_NAME = 'localhost:8000'
SECRET_KEY = 'insecurekeyfordev'

SECRET_KEY = os.getenv('SECRET_KEY', None)

SERVER_NAME = os.getenv('SERVER_NAME',
'localhost:{0}'.format(os.getenv('DOCKER_WEB_PORT',
'8000')))

# Flask-Mail.
MAIL_DEFAULT_SENDER = 'contact@local.host'
MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USE_SSL = False
MAIL_USERNAME = 'you@gmail.com'
MAIL_PASSWORD = 'awesomepassword'
MAIL_SERVER = os.getenv('MAIL_SERVER', 'smtp.gmail.com')
MAIL_PORT = os.getenv('MAIL_PORT', 587)
MAIL_USE_TLS = bool(strtobool(os.getenv('MAIL_USE_TLS', 'true')))
MAIL_USE_SSL = bool(strtobool(os.getenv('MAIL_USE_SSL', 'false')))
MAIL_USERNAME = os.getenv('MAIL_USERNAME', None)
MAIL_PASSWORD = os.getenv('MAIL_PASSWORD', None)
MAIL_DEFAULT_SENDER = os.getenv('MAIL_DEFAULT_SENDER', 'smtp.gmail.com')

# Celery.
CELERY_BROKER_URL = 'redis://:devpassword@redis:6379/0'
CELERY_RESULT_BACKEND = 'redis://:devpassword@redis:6379/0'
CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL', 'redis://redis:6379/0')
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
Expand Down
61 changes: 39 additions & 22 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,52 @@
version: '2'
version: "3.4"

services:
redis:
image: 'redis:4.0-alpine'
command: redis-server --requirepass devpassword
env_file:
- ".env"
image: "redis:5.0.4-stretch"
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "${DOCKER_STOP_GRACE_PERIOD:-3s}"
volumes:
- 'redis:/var/lib/redis/data'
ports:
- '6379:6379'
- "redis:/data"

website:
build: .
command: >
gunicorn -b 0.0.0.0:8000
--access-logfile -
--reload
"snakeeyes.app:create_app()"
web:
build:
context: "."
args:
- "FLASK_ENV=${FLASK_ENV:-production}"
depends_on:
- "redis"
env_file:
- '.env'
volumes:
- '.:/app'
- ".env"
healthcheck:
test: "${DOCKER_HEALTHCHECK_TEST:-curl localhost:8000/healthy}"
interval: "60s"
timeout: "3s"
start_period: "5s"
retries: 3
ports:
- '8000:8000'
- "${DOCKER_WEB_PORT:-127.0.0.1:8000}:8000"
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "${DOCKER_STOP_GRACE_PERIOD:-3s}"
volumes:
- "${DOCKER_WEB_VOLUME:-./public:/app/public}"

celery:
build: .
worker:
build:
context: "."
args:
- "FLASK_ENV=${FLASK_ENV:-production}"
command: celery worker -B -l info -A snakeeyes.blueprints.contact.tasks
depends_on:
- "redis"
env_file:
- '.env'
- ".env"
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "${DOCKER_STOP_GRACE_PERIOD:-3s}"
volumes:
- '.:/app'
- "${DOCKER_WEB_VOLUME:-./public:/app/public}"

volumes:
redis:
redis: {}

Empty file removed instance/__init__.py
Empty file.
10 changes: 0 additions & 10 deletions instance/settings.py.production_example

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 1 addition & 2 deletions snakeeyes/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ def create_app(settings_override=None):
:param settings_override: Override settings
:return: Flask app
"""
app = Flask(__name__, instance_relative_config=True)
app = Flask(__name__, static_folder='../public', static_url_path='')

app.config.from_object('config.settings')
app.config.from_pyfile('settings.py', silent=True)

if settings_override:
app.config.update(settings_override)
Expand Down
5 changes: 5 additions & 0 deletions snakeeyes/blueprints/page/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ def terms():
@page.route('/privacy')
def privacy():
return render_template('page/privacy.html')


@page.route('/healthy')
def healthy():
return ''
2 changes: 1 addition & 1 deletion snakeeyes/templates/layouts/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
<footer class="footer text-center">
<div class="container">
<ul class="list-inline">
<li class="text-muted">Snake Eyes &copy; 2016</li>
<li class="text-muted">Snake Eyes &copy; 2019</li>
<li><a href="{{ url_for('contact.index') }}">Contact</a></li>
<li><a href="{{ url_for('page.privacy') }}">Privacy Policy</a></li>
<li><a href="{{ url_for('page.terms') }}">Terms of Service</a></li>
Expand Down

0 comments on commit 0f9eee3

Please sign in to comment.