diff --git a/{{cookiecutter.repo_name}}/Dockerfile b/{{cookiecutter.repo_name}}/Dockerfile new file mode 100644 index 00000000..bb319026 --- /dev/null +++ b/{{cookiecutter.repo_name}}/Dockerfile @@ -0,0 +1,28 @@ +FROM python:2.7 +ENV PYTHONUNBUFFERED 1 + +RUN groupadd -r django && useradd -r -g django django + +RUN apt-get update +RUN apt-get -y install libmemcached-dev + +# Requirements have to be pulled and installed here, otherwise caching won't work +ADD ./requirements /requirements +ADD ./requirements.txt /requirements.txt + +RUN pip install -r /requirements.txt +RUN pip install -r /requirements/local.txt + +ADD . /app + +ADD ./compose/django/gunicorn.sh /gunicorn.sh +ADD ./compose/django/entrypoint.sh /entrypoint.sh + +RUN chmod +x /entrypoint.sh +RUN chmod +x /gunicorn.sh + +RUN chown -R django /app + +WORKDIR /app + +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/{{cookiecutter.repo_name}}/README.rst b/{{cookiecutter.repo_name}}/README.rst index 81f5d58e..5a2fa450 100644 --- a/{{cookiecutter.repo_name}}/README.rst +++ b/{{cookiecutter.repo_name}}/README.rst @@ -200,7 +200,7 @@ The testing framework runs Django, Celery (if enabled), Postgres, HitchSMTP (a m Deployment ---------- -It is possible to deploy to Heroku or to your own server by using Dokku, an open source Heroku clone. +It is possible to deploy to Heroku, to your own server by using Dokku, an open source Heroku clone or using docker-compose. Heroku ^^^^^^ @@ -277,3 +277,17 @@ You can then deploy by running the following commands. ssh -t dokku@yourservername.com dokku run {{cookiecutter.repo_name}} python manage.py createsuperuser When deploying via Dokku make sure you backup your database in some fashion as it is NOT done automatically. + +Docker +^^^^^^ + +You need a working docker and docker-compose installation on your production server. + +To get started, clone the git repo containing your projects code and set all needed environment variables in +``env.production``. + +To start docker-compose in the foreground, run: + +.. code-block:: bash + + docker-compose up diff --git a/{{cookiecutter.repo_name}}/compose/django/entrypoint.sh b/{{cookiecutter.repo_name}}/compose/django/entrypoint.sh new file mode 100644 index 00000000..7b3ae746 --- /dev/null +++ b/{{cookiecutter.repo_name}}/compose/django/entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e + +# setting up environment variables to work with DATABASE_URL and DJANGO_CACHE_URL +export DJANGO_CACHE_URL=redis://redis:6379 + +if [ -z "$POSTGRES_ENV_POSTGRES_USER" ]; then + export POSTGRES_ENV_POSTGRES_USER=postgres +fi + +export DATABASE_URL=postgres://$POSTGRES_ENV_POSTGRES_USER:$POSTGRES_ENV_POSTGRES_PASSWORD@postgres:5432/$POSTGRES_ENV_POSTGRES_USER +{% if cookiecutter.use_celery %} +export CELERY_BROKER_URL=amqp://guest:guest@rabbitmq:5672// +{% endif %} +exec "$@" \ No newline at end of file diff --git a/{{cookiecutter.repo_name}}/compose/django/gunicorn.sh b/{{cookiecutter.repo_name}}/compose/django/gunicorn.sh new file mode 100644 index 00000000..3f9f09ec --- /dev/null +++ b/{{cookiecutter.repo_name}}/compose/django/gunicorn.sh @@ -0,0 +1,3 @@ +#!/bin/sh +su -m django -c "python /app/manage.py collectstatic --noinput" +su -m django -c "/usr/local/bin/gunicorn config.wsgi -w 4 -b 0.0.0.0:5000 --chdir=/app" \ No newline at end of file diff --git a/{{cookiecutter.repo_name}}/compose/nginx/Dockerfile b/{{cookiecutter.repo_name}}/compose/nginx/Dockerfile new file mode 100644 index 00000000..19639576 --- /dev/null +++ b/{{cookiecutter.repo_name}}/compose/nginx/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx:latest +ADD nginx.conf /etc/nginx/nginx.conf \ No newline at end of file diff --git a/{{cookiecutter.repo_name}}/compose/nginx/nginx.conf b/{{cookiecutter.repo_name}}/compose/nginx/nginx.conf new file mode 100644 index 00000000..720b22e5 --- /dev/null +++ b/{{cookiecutter.repo_name}}/compose/nginx/nginx.conf @@ -0,0 +1,53 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + upstream app { + server django:5000; + } + + server { + listen 80; + charset utf-8; + + + location / { + # checks for static file, if not found proxy to app + try_files $uri @proxy_to_app; + } + + location @proxy_to_app { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_redirect off; + + proxy_pass http://app; + } + + } +} \ No newline at end of file diff --git a/{{cookiecutter.repo_name}}/dev.yml b/{{cookiecutter.repo_name}}/dev.yml new file mode 100644 index 00000000..98146ffe --- /dev/null +++ b/{{cookiecutter.repo_name}}/dev.yml @@ -0,0 +1,16 @@ +postgres: + image: postgres + volumes: + # If you are using boot2docker, postgres data has to live in the VM for now until #581 is fixed + # for more info see here: https://github.com/boot2docker/boot2docker/issues/581 + - /data/{{cookiecutter.repo_name}}/postgres:/var/lib/postgresql/data + +django: + build: . + command: python /app/manage.py runserver_plus 0.0.0.0:8000 + volumes: + - .:/app + ports: + - "8000:8000" + links: + - postgres \ No newline at end of file diff --git a/{{cookiecutter.repo_name}}/docker-compose.yml b/{{cookiecutter.repo_name}}/docker-compose.yml new file mode 100644 index 00000000..2f8154c9 --- /dev/null +++ b/{{cookiecutter.repo_name}}/docker-compose.yml @@ -0,0 +1,48 @@ +postgres: + image: postgres:9.4 + volumes: + - /data/{{cookiecutter.repo_name}}/postgres:/var/lib/postgresql/data + env_file: env.production + +django: + build: . + links: + - postgres + - redis + {% if cookiecutter.use_celery %} + - rabbitmq + {% endif %} + command: /gunicorn.sh + env_file: env.production + +nginx: + build: ./compose/nginx + links: + - django + ports: + - "0.0.0.0:80:80" + +redis: + image: redis:3.0 +{% if cookiecutter.use_celery %} +rabbitmq: + image: rabbitmq + +celeryworker: + build: . + env_file: env.production + links: + - rabbitmq + - postgres + - redis + command: su -m django -c "celery -A {{cookiecutter.repo_name}}.taskapp worker -l INFO" + +celerybeat: + build: . + env_file: env.production + links: + - rabbitmq + - postgres + - redis + command: su -m django -c "celery -A {{cookiecutter.repo_name}}.taskapp beat -l INFO" +{% endif %} \ No newline at end of file diff --git a/{{cookiecutter.repo_name}}/env.production b/{{cookiecutter.repo_name}}/env.production new file mode 100644 index 00000000..b4375324 --- /dev/null +++ b/{{cookiecutter.repo_name}}/env.production @@ -0,0 +1,12 @@ +POSTGRES_PASSWORD=mysecretpass +POSTGRES_USER=postgresuser + +DJANGO_SETTINGS_MODULE=config.settings.production +DJANGO_SECRET_KEY= +DJANGO_AWS_ACCESS_KEY_ID= +DJANGO_AWS_SECRET_ACCESS_KEY= +DJANGO_AWS_STORAGE_BUCKET_NAME= +DJANGO_MAILGUN_API_KEY= +DJANGO_MAILGUN_SERVER_NAME= +DJANGO_SERVER_EMAIL= +DJANGO_SECURE_SSL_REDIRECT=False \ No newline at end of file