├── .gitignore ├── CONTRIBUTING.rst ├── Dockerfile ├── Dockerrun.aws.json ├── LICENSE ├── README.md ├── db.sqlite3 ├── deploy ├── container_start.sh ├── gunicorn.conf ├── scripts │ ├── __init__.py │ └── deploy_docs.py ├── supervisor_conf.d │ └── webapp.conf └── webapp.nginxconf ├── manage.py ├── mysite ├── __init__.py ├── apps │ └── __init__.py ├── core │ ├── __init__.py │ ├── urls.py │ └── wsgi.py ├── db.sqlite3 └── settings │ ├── __init__.py │ └── base.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.pyo 3 | .installed.cfg 4 | bin 5 | develop-eggs 6 | dist 7 | downloads 8 | eggs 9 | parts 10 | src/*.egg-info 11 | lib 12 | lib64 13 | .idea/ 14 | /static/ 15 | workspace.xml 16 | /env/ 17 | /*.ini 18 | /cover/ 19 | /ssl/ 20 | .DS_Store 21 | *.DS_Store 22 | 23 | # Elastic Beanstalk Files 24 | .elasticbeanstalk/* 25 | !.elasticbeanstalk/*.cfg.yml 26 | !.elasticbeanstalk/*.global.yml 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glynjackson/django-docker-template/f47c2c74d3bd58cca714a94133b299674857f778/CONTRIBUTING.rst -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Base python 3.4 build, inspired by https://github.com/Pakebo/eb-docker-django-simple 2 | # Python 3.4 | Django 3 | 4 | FROM python:3.4 5 | MAINTAINER Glyn Jackson (me@glynjackson.org) 6 | 7 | ############################################################################## 8 | # Environment variables 9 | ############################################################################## 10 | # Get noninteractive frontend for Debian to avoid some problems: 11 | # debconf: unable to initialize frontend: Dialog 12 | ENV DEBIAN_FRONTEND noninteractive 13 | 14 | ############################################################################## 15 | # OS Updates and Python packages 16 | ############################################################################## 17 | 18 | RUN apt-get update \ 19 | && apt-get upgrade -y \ 20 | && apt-get install -y 21 | 22 | RUN apt-get install -y apt-utils 23 | # Libs required for geospatial libraries on Debian... 24 | RUN apt-get -y install binutils libproj-dev gdal-bin 25 | 26 | ############################################################################## 27 | # A Few pip installs not commonly in requirements.txt 28 | ############################################################################## 29 | 30 | RUN apt-get install -y nano wget 31 | # build dependencies for postgres and image bindings 32 | RUN apt-get install -y python-imaging python-psycopg2 33 | 34 | ############################################################################## 35 | # setup startup script for gunicord WSGI service 36 | ############################################################################## 37 | 38 | RUN groupadd webapps 39 | RUN useradd webapp -G webapps 40 | RUN mkdir -p /var/log/webapp/ && chown -R webapp /var/log/webapp/ && chmod -R u+rX /var/log/webapp/ 41 | RUN mkdir -p /var/run/webapp/ && chown -R webapp /var/run/webapp/ && chmod -R u+rX /var/run/webapp/ 42 | 43 | ############################################################################## 44 | # Install and configure supervisord 45 | ############################################################################## 46 | 47 | RUN apt-get install -y supervisor 48 | RUN mkdir -p /var/log/supervisor 49 | ADD ./deploy/supervisor_conf.d/webapp.conf /etc/supervisor/conf.d/webapp.conf 50 | 51 | ############################################################################## 52 | # Install dependencies and run scripts. 53 | ############################################################################## 54 | 55 | ADD . /var/projects/mysite 56 | WORKDIR /var/projects/mysite 57 | RUN pip install -r requirements.txt 58 | 59 | ############################################################################## 60 | # Run start.sh script when the container starts. 61 | # Note: If you run migrations etc outside CMD, envs won't be available! 62 | ############################################################################## 63 | CMD ["sh", "./deploy/container_start.sh"] 64 | 65 | # Expose listen ports 66 | EXPOSE 8002 67 | -------------------------------------------------------------------------------- /Dockerrun.aws.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSEBDockerrunVersion": "1", 3 | "Logging": "/var/eb_log" 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Glyn Jackson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Elastic Beanstalk Docker template for Django 3 | ============================================ 4 | 5 | Part 1 of tutorial: http://glynjackson.org/weblog/tutorial-deploying-django-app-aws-elastic-beanstalk-using-docker/ 6 | Boilerplate Docker template for Django 1.8+ running Python 3.4.+ on AWS's Elastic Beanstalk. 7 | 8 | 9 | Starting your project 10 | --------------------- 11 | 12 | Run the following command:: 13 | 14 | $ django-admin.py startproject --template=https://github.com/glynjackson/django-docker-template/zipball/master mysite 15 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glynjackson/django-docker-template/f47c2c74d3bd58cca714a94133b299674857f778/db.sqlite3 -------------------------------------------------------------------------------- /deploy/container_start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd /var/projects/mysite && python manage.py migrate --noinput 3 | supervisord -n -c /etc/supervisor/supervisord.conf -------------------------------------------------------------------------------- /deploy/gunicorn.conf: -------------------------------------------------------------------------------- 1 | backlog = 2048 2 | chdir = "/var/projects/mysite" 3 | bind = "0.0.0.0:8002" 4 | pidfile = "/var/run/webapp/gunicorn.pid" 5 | daemon = False 6 | debug = False 7 | workers = 4 8 | accesslog = "/var/log/webapp/gunicorn-webapp-access.log" 9 | errorlog = "/var/log/webapp/gunicorn-webapp-error.log" 10 | loglevel = "debug" # was info 11 | proc_name = "webapp" 12 | user = "webapp" 13 | umask = 0000 -------------------------------------------------------------------------------- /deploy/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'glyn' 2 | -------------------------------------------------------------------------------- /deploy/scripts/deploy_docs.py: -------------------------------------------------------------------------------- 1 | import os 2 | import boto3 3 | 4 | AWS_ACCESS_KEY_ID = '' 5 | AWS_ACCESS_KEY_SECRET = '' 6 | bucket_name = '' 7 | sourceDir = "../../docs/build/html/" 8 | destDir = '' 9 | 10 | r = boto3.setup_default_session(region_name='eu-west-1') 11 | s3 = boto3.resource('s3', aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_ACCESS_KEY_SECRET) 12 | bucket = s3.Bucket(bucket_name) 13 | uploadFileNames = [] 14 | # for (sourceDir, dirname, filenames) in os.walk(sourceDir): 15 | # for filename in filenames: 16 | # bucket.put_object(Key=filename, Body=open("{}{}".format(sourceDir, filename), "rb")) 17 | # break 18 | 19 | for subdir, dirs, files in os.walk(sourceDir): 20 | for file in files: 21 | this_file = "{}/".format(subdir.split('html/', 1)[1]) 22 | if this_file == "/": 23 | upload_file = file 24 | else: 25 | upload_file = "{}{}".format(this_file, file) 26 | 27 | file_type = file.rsplit('.', 1)[1] 28 | 29 | if file_type == "html": 30 | content_type = 'text/html' 31 | elif file_type == "css": 32 | content_type = 'text/css' 33 | else: 34 | content_type = 'binary/octet-stream' 35 | 36 | bucket.put_object(Key=upload_file, Body=open("{}/{}".format(subdir, file), "rb"), ContentType=content_type) 37 | 38 | -------------------------------------------------------------------------------- /deploy/supervisor_conf.d/webapp.conf: -------------------------------------------------------------------------------- 1 | ; ======= 2 | ; Django 3 | ; ======= 4 | 5 | [program:webapp] 6 | directory=/var/projects/mysite/ 7 | environment=DJANGO_SETTINGS_MODULE="mysite.settings" 8 | command=gunicorn mysite.core.wsgi:application -c /var/projects/mysite/deploy/gunicorn.conf 9 | autostart=true 10 | autorestart=true 11 | stdout_logfile = /var/log/webapp/gunicorn_supervisor.log ; Where to write log messages 12 | redirect_stderr=True 13 | user=webapp -------------------------------------------------------------------------------- /deploy/webapp.nginxconf: -------------------------------------------------------------------------------- 1 | 2 | # This file belongs in /etc/nginx/sites-available/webapp.nginxconf 3 | 4 | upstream webapp_server { 5 | # fail_timeout=0 means we always retry an upstream even if it failed 6 | # to return a good HTTP response (in case the Unicorn master nukes a 7 | # single worker for timing out). 8 | server unix:/var/run/webapp/gunicorn.sock fail_timeout=0; 9 | } 10 | 11 | 12 | server { 13 | listen 80 default_server; 14 | #server_name webapp.com; 15 | client_max_body_size 20M; 16 | access_log /var/log/webapp/nginx-access.log; 17 | error_log /var/log/webapp/nginx-error.log; 18 | 19 | 20 | # the static dir auto-populated with the media of django apps 21 | location /static/ { 22 | alias /var/projects/mysite/static/; 23 | } 24 | 25 | 26 | location / { 27 | # an HTTP header important enough to have its own Wikipedia entry: 28 | # http://en.wikipedia.org/wiki/X-Forwarded-For 29 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 30 | 31 | # enable this if and only if you use HTTPS, this helps Rack 32 | # set the proper protocol for doing redirects: 33 | # proxy_set_header X-Forwarded-Proto https; 34 | 35 | # pass the Host: header from the client right along so redirects 36 | # can be set properly within the Rack application 37 | proxy_set_header Host $http_host; 38 | 39 | # we don't want nginx trying to do something clever with 40 | # redirects, we set the Host: header above already. 41 | proxy_redirect off; 42 | 43 | # set "proxy_buffering off" *only* for Rainbows! when doing 44 | # Comet/long-poll stuff. It's also safe to set if you're 45 | # using only serving fast clients with Unicorn + nginx. 46 | # Otherwise you _want_ nginx to buffer responses to slow 47 | # clients, really. 48 | # proxy_buffering off; 49 | 50 | # Try to serve static files from nginx, no point in making an 51 | # *application* server like Unicorn/Rainbows! serve static files. 52 | if (!-f $request_filename) { 53 | proxy_pass http://webapp_server; 54 | break; 55 | } 56 | } 57 | 58 | # Error pages 59 | error_page 500 502 503 504 /500.html; 60 | location = /500.html { 61 | root /var/projects/mysite/static/; 62 | } 63 | } 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glynjackson/django-docker-template/f47c2c74d3bd58cca714a94133b299674857f778/mysite/__init__.py -------------------------------------------------------------------------------- /mysite/apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glynjackson/django-docker-template/f47c2c74d3bd58cca714a94133b299674857f778/mysite/apps/__init__.py -------------------------------------------------------------------------------- /mysite/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glynjackson/django-docker-template/f47c2c74d3bd58cca714a94133b299674857f778/mysite/core/__init__.py -------------------------------------------------------------------------------- /mysite/core/urls.py: -------------------------------------------------------------------------------- 1 | """mysite URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.8/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Add an import: from blog import urls as blog_urls 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) 15 | """ 16 | from django.conf.urls import include, url 17 | from django.contrib import admin 18 | 19 | urlpatterns = [ 20 | url(r'^admin/', include(admin.site.urls)), 21 | ] 22 | -------------------------------------------------------------------------------- /mysite/core/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /mysite/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glynjackson/django-docker-template/f47c2c74d3bd58cca714a94133b299674857f778/mysite/db.sqlite3 -------------------------------------------------------------------------------- /mysite/settings/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .base import * -------------------------------------------------------------------------------- /mysite/settings/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for mysite project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.8.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.8/ref/settings/ 11 | """ 12 | 13 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 14 | import os 15 | 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '$ldwp&agzxkb$brgp2^0gw*nxtrwr)lv&u^y^66j=57bq3xwoe' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = ( 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | ) 41 | 42 | MIDDLEWARE_CLASSES = ( 43 | 'django.contrib.sessions.middleware.SessionMiddleware', 44 | 'django.middleware.common.CommonMiddleware', 45 | 'django.middleware.csrf.CsrfViewMiddleware', 46 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 47 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 48 | 'django.contrib.messages.middleware.MessageMiddleware', 49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 50 | 'django.middleware.security.SecurityMiddleware', 51 | ) 52 | 53 | ROOT_URLCONF = 'mysite.core.urls' 54 | 55 | TEMPLATES = [ 56 | { 57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 58 | 'DIRS': [], 59 | 'APP_DIRS': True, 60 | 'OPTIONS': { 61 | 'context_processors': [ 62 | 'django.template.context_processors.debug', 63 | 'django.template.context_processors.request', 64 | 'django.contrib.auth.context_processors.auth', 65 | 'django.contrib.messages.context_processors.messages', 66 | ], 67 | }, 68 | }, 69 | ] 70 | 71 | WSGI_APPLICATION = 'mysite.core.wsgi.application' 72 | 73 | # Database 74 | # https://docs.djangoproject.com/en/1.8/ref/settings/#databases 75 | 76 | DATABASES = { 77 | 'default': { 78 | 'ENGINE': 'django.db.backends.sqlite3', 79 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 80 | } 81 | } 82 | 83 | 84 | # Internationalization 85 | # https://docs.djangoproject.com/en/1.8/topics/i18n/ 86 | 87 | LANGUAGE_CODE = 'en-us' 88 | 89 | TIME_ZONE = 'UTC' 90 | 91 | USE_I18N = True 92 | 93 | USE_L10N = True 94 | 95 | USE_TZ = True 96 | 97 | 98 | # Static files (CSS, JavaScript, Images) 99 | # https://docs.djangoproject.com/en/1.8/howto/static-files/ 100 | 101 | STATIC_URL = '/static/' 102 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | django>=1.8.4,<1.9 2 | gevent==1.1a2 3 | gunicorn==19.3.0 --------------------------------------------------------------------------------