From 53ed002440eb61cc04523923ed2c6be48facf9a4 Mon Sep 17 00:00:00 2001 From: Jonathan Rosenbaum Date: Sun, 10 Sep 2017 18:20:12 +0000 Subject: [PATCH] Create a demo (production) with docker compose! * Will alter to allow environment configurations. --- Dockerfile | 1 + Dockerfile-nginx | 10 +++++ default.conf | 61 ++++++++++++++++++++++++++++ docker-compose.demo.yml | 88 +++++++++++++++++++++++++++++++++++++++++ production.py | 69 ++++++++++++++++++++++++++++++++ 5 files changed, 229 insertions(+) create mode 100644 Dockerfile-nginx create mode 100644 default.conf create mode 100644 docker-compose.demo.yml create mode 100644 production.py diff --git a/Dockerfile b/Dockerfile index 1d3a352..961dfcc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,7 @@ ADD bikeshop_project /code ADD requirements/base.txt /code/requirements/base.txt ADD requirements/testing.txt /code/requirements/testing.txt ADD requirements/production.txt /code/requirements/production.txt +COPY production.py /code/bikeshop/settings RUN pip install -r requirements/production.txt RUN npm cache clean ADD ./bikeshop_project/bower.json bower.json diff --git a/Dockerfile-nginx b/Dockerfile-nginx new file mode 100644 index 0000000..ad603db --- /dev/null +++ b/Dockerfile-nginx @@ -0,0 +1,10 @@ +#################### +# workstand-nginx # +#################### + +FROM nginx:1.11-alpine + +MAINTAINER Jonathan Rosenbaum + +COPY default.conf /etc/nginx/conf.d +RUN mkdir /usr/share/nginx/html/static diff --git a/default.conf b/default.conf new file mode 100644 index 0000000..0bc0ec4 --- /dev/null +++ b/default.conf @@ -0,0 +1,61 @@ +server { + listen 80; + server_name localhost; + + #charset koi8-r; + #access_log /var/log/nginx/log/host.access.log main; + + + location / { + # checks for static file, if not found proxy to app + try_files $uri @proxy_to_app; + } + + location /static { + root /usr/share/nginx/html; + } + + location @proxy_to_app { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # enable this if and only if you use HTTPS + # proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + # we don't want nginx trying to do something clever with + # redirects, we set the Host: header above already. + proxy_redirect off; + proxy_pass http://workstand:8000; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} +} + diff --git a/docker-compose.demo.yml b/docker-compose.demo.yml new file mode 100644 index 0000000..4eb0181 --- /dev/null +++ b/docker-compose.demo.yml @@ -0,0 +1,88 @@ +# The environment is setup to use jwilder/nginx-proxy and +# JrCs/docker-letsencrypt-nginx-proxy-companion but can easily be +# modified to be served by an alternative http server. + +# docker-compose build +# docker-compose up -d + +# bikeshop/settings/production.py will need ALLOWED_HOSTS altered correctly + +version: "2" +services: + + nginx: + container_name: workstand-nginx + image: workstand-nginx + build: + context: . + dockerfile: Dockerfile-nginx + volumes: + - static:/usr/share/nginx/html/static + links: + - workstand + network_mode: "bridge" + environment: + - VIRTUAL_HOST=workstand.bikelover.org + - LETSENCRYPT_HOST=workstand.bikelover.org + - LETSENCRYPT_EMAIL=bike@bikelover.org + restart: always + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + workstand: + container_name: workstand + build: + context: . + dockerfile: Dockerfile + command: 'bash -c "PYTHONUNBUFFERED=TRUE python manage.py migrate --no-input && python manage.py collectstatic --no-input && python manage.py rebuild_index --noinput && python manage.py loaddata fixtures.yaml && gunicorn --log-file=- -b 0.0.0.0:8000 bikeshop.wsgi:application"' + network_mode: "bridge" + image: bcbc/workstand:production + links: + - redis + - db + environment: + - DJANGO_SETTINGS_MODULE=bikeshop.settings.production + - PORT=8000 + volumes: + - static:/code/static + restart: always + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + redis: + container_name: workstand-redis + network_mode: "bridge" + image: redis:latest + volumes: + - redis:/data + restart: always + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + db: + container_name: workstand-db + network_mode: "bridge" + image: postgres:latest + volumes: + - pgdata:/var/lib/postgresql/data/ + restart: always + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + +volumes: + pgdata: + external: false + redis: + static: diff --git a/production.py b/production.py new file mode 100644 index 0000000..13eace9 --- /dev/null +++ b/production.py @@ -0,0 +1,69 @@ +import os +import sys +import rollbar + +from .base import * # noqa + + +# SECURITY WARNING: keep the secret key used in production secret! +WSGI_APPLICATION = 'bikeshop.wsgi.application' + +SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'secret') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False + +ALLOWED_HOSTS = ['workstand.bikelover.org'] + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'formatter': 'verbose' + }, + }, + 'formatters': { + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(pathname)s %(message)s' + }, + }, + 'loggers': { + 'django': { + 'handlers': ['console'], + 'level': os.getenv('DJANGO_LOG_LEVEL', 'ERROR'), + }, + 'bikeshop': { + 'handlers': ['console'], + 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), + } + }, +} + +WEBPACK_LOADER = { + 'DEFAULT': { + 'CACHE': True, + 'BUNDLE_DIR_NAME': 'dist/', # must end with slash + 'STATS_FILE': os.path.join(BASE_DIR, '../webpack-stats-prod.json'), # noqa + 'POLL_INTERVAL': 0.1, + 'IGNORE': ['.+\.hot-update.js', '.+\.map'] + } +} + +# Covers regular testing and django-coverage +if 'test' in sys.argv or 'test_coverage' in sys.argv: + DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3' # noqa + +MIDDLEWARE_CLASSES += ['rollbar.contrib.django.middleware.RollbarNotifierMiddleware'] + +ROLLBAR = { + 'access_token': '91808a727b9a4679a89720132071391a', + 'environment': 'production', + 'root': BASE_DIR, +} + +rollbar.init(**ROLLBAR) + +MAILCHIMP_API_KEY = os.environ.get('MAILCHIMP_API_KEY') +MAILCHIMP_USERNAME = 'drew@bcbc.bike'