Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
53d5a6c
Changed, how tox manages its requirements
Mischback Jan 14, 2020
781f84d
Building the context for Docker
Mischback Jan 17, 2020
06d2685
Minor Makefile improvements
Mischback Jan 17, 2020
1226080
Working on Django Dockerfile
Mischback Jan 20, 2020
7bae76b
Switching to userspace
Mischback Jan 27, 2020
d3195c2
Started docker-compose.yml
Mischback Jan 27, 2020
e1ca71a
Testing another Dockerfile structure
Mischback Jan 28, 2020
050faa3
Tag docker builds with git's commit hash
Mischback Jan 29, 2020
f4ad8d0
Update Dockerfile to automatically generate requirements
Mischback Jan 29, 2020
441f42e
More and better tagging of images
Mischback Jan 30, 2020
dee83ce
Introducing pip-tools
Mischback Jan 30, 2020
8494a59
Generate requirements files with tox
Mischback Jan 31, 2020
dd3b911
Actually use the built requirements in the Dockerfile
Mischback Feb 4, 2020
4df5af9
Activate the virtual environment
Mischback Feb 4, 2020
88bc9e9
Provide a default CMD
Mischback Feb 4, 2020
ce70296
Restart Makefile
Mischback Feb 5, 2020
1594758
Modify tox.ini to allow Docker related testing during development
Mischback Feb 6, 2020
de410ef
Fetched Makefile.deployment
Mischback Feb 9, 2020
13a33d0
Actually switching Makefile and tox.ini
Mischback Feb 9, 2020
d60adb3
Prepare colourful output
Mischback Feb 10, 2020
0fb1ff9
Add colours to the output
Mischback Feb 10, 2020
1833936
Makefile supports Docker build step
Mischback Feb 11, 2020
713136d
Removed outdated Makefile backup
Mischback Feb 11, 2020
ea118f2
Renamed the apache2 config to match new file naming scheme
Mischback Feb 11, 2020
993665f
Removed unnecessary line from Makefile
Mischback Feb 11, 2020
dd6cb67
Comments on get_build_id.sh
Mischback Feb 12, 2020
0db25cb
Adjust .dockerignore to exclude all deployment related utility files
Mischback Feb 12, 2020
f90e1a5
Building Docker images using the tox environment
Mischback Feb 12, 2020
4252d84
Merge branch 'makefile' into docker-dev
Mischback Feb 12, 2020
78d65b2
Fetched utility script to install packages
Mischback Feb 15, 2020
3831b6f
Prepare usage of this utility script
Mischback Feb 15, 2020
8ea8c56
Make the container runnable
Mischback Feb 15, 2020
1c63abb
Transfer docker command to Makefile.deployment
Mischback Feb 15, 2020
54e6ac7
Place Docker-related scripts in their own directory
Mischback Feb 15, 2020
4733a15
Added gunicorn to the stack
Mischback Feb 15, 2020
b1ca417
API BREAK
Mischback Feb 16, 2020
e8cfb2e
Merge branch 'docker-django' into feature/docker
Mischback Feb 16, 2020
397858b
Basic working nginx/gunicorn combination
Mischback Feb 16, 2020
221f1d5
Provide a gunicorn configuration by file
Mischback Feb 18, 2020
3e97e38
Minor modification of Makefile
Mischback Feb 18, 2020
81b7100
Do not expose Gunicorn publicly
Mischback Feb 18, 2020
e4c3761
Dropping support for Django < 1.11
Mischback Feb 21, 2020
ea824a0
Renamed project specific templates
Mischback Feb 25, 2020
d8d6625
Preparing nginx utility
Mischback Feb 25, 2020
ffa8f6f
Moving Django-related script into django directory
Mischback Feb 25, 2020
6d26041
Comments on the environment file
Mischback Feb 26, 2020
c7a30eb
Update .dockerignore
Mischback Feb 26, 2020
9828277
Adjusting imports in settings files
Mischback Feb 27, 2020
cd009e0
Fixed typo in Makefile (deployment)
Mischback Feb 27, 2020
7080a01
Fixed string fomratting in settings files
Mischback Feb 27, 2020
fc3fd3f
Make Django configurable by environment variables
Mischback Feb 27, 2020
4af865d
Minor documentation issue
Mischback Feb 27, 2020
39bed57
Got stuck with Django's logging inside of the container
Mischback Feb 27, 2020
c05ed23
Added formatter and root logger
Mischback Feb 28, 2020
f072c0d
Logging from Django actually works
Mischback Feb 28, 2020
49f7071
Updated the formatter
Mischback Feb 28, 2020
f7b162f
Fix Django to 2.2
Mischback Feb 28, 2020
b8e3ebe
Completed logging Django container
Mischback Feb 28, 2020
76b6c2a
Adjusted Gunicorn's default access log format
Mischback Feb 28, 2020
7d6cd6a
Introduced overall log level
Mischback Feb 28, 2020
ae962f4
Merge branch 'django-logging' into feature/docker
Mischback Feb 28, 2020
aa1f343
Fetching SECRET_KEY from the environment
Mischback Feb 29, 2020
4dcb49a
Automatically create production environment file by Makefile
Mischback Feb 29, 2020
aeeddd7
Automatically generate a SECRET_KEY in env.production
Mischback Mar 1, 2020
e580fd6
env.production must be generated in both Makefiles
Mischback Mar 1, 2020
18c871a
Remove env.production during development's clean
Mischback Mar 1, 2020
fb7e72e
Some more comments on generating SECRET_KEY
Mischback Mar 1, 2020
c018180
Added volume for static files
Mischback Mar 2, 2020
764640e
Recreate nginx.conf
Mischback Mar 3, 2020
2866c49
Synchronize time between host and containers
Mischback Mar 3, 2020
5c6810d
Revoke last change
Mischback Mar 4, 2020
191604a
Introduce project specific time zone setting
Mischback Mar 4, 2020
4a05f13
Use an entrypoint script to set container's time correctly
Mischback Mar 4, 2020
1752cca
Clean Django Dockerfile
Mischback Mar 4, 2020
f188365
Make setting the time zone DRY
Mischback Mar 5, 2020
9f1c52e
Renamed Debian install script
Mischback Mar 5, 2020
f8c2dab
Renamed some more scripts
Mischback Mar 5, 2020
35d7fe5
Applied time zone setting to nginx container
Mischback Mar 5, 2020
3d717f5
Improved apt-get_install cleaning
Mischback Mar 9, 2020
b834e3f
Applied -euo pipefail to all shell scripts
Mischback Mar 9, 2020
a937320
Implement environment variable substitution in nginx.conf
Mischback Mar 9, 2020
95004b3
nginx.conf server_name
Mischback Mar 10, 2020
a03b369
nginx.conf server_tokens
Mischback Mar 10, 2020
72246f0
nginx.conf STATIC_URL
Mischback Mar 13, 2020
a2857e6
nginx.conf keepalive_timeout
Mischback Mar 13, 2020
38f54a9
nginx.conf keepalive
Mischback Mar 13, 2020
469fc25
nginx.conf keepalive_requests
Mischback Mar 13, 2020
a7d0efc
nginx.conf server_name (again)
Mischback Mar 13, 2020
929c80b
nginx.conf keepalive_timeout
Mischback Mar 17, 2020
d0b605c
nginx.conf Added upstream keyword
Mischback Mar 17, 2020
740829b
nginx.conf Added gzip support
Mischback Mar 18, 2020
b4eabd9
Switch to ManifestStaticFilesStorage
Mischback Mar 19, 2020
521b1d5
Created init directory
Mischback Mar 25, 2020
dbdc34d
Created util directory
Mischback Mar 25, 2020
22fdc41
Moved project-specific bin to util
Mischback Mar 25, 2020
5b63b08
Moved deployment-related files to util/deployment
Mischback Mar 25, 2020
76fa37c
Renamed doc to docs
Mischback Mar 25, 2020
3c04850
Fixed Makefile tree
Mischback Mar 25, 2020
9934aca
Provided hardcoded name for project-specific directory
Mischback Mar 25, 2020
5eaadb4
Moved deployment-related files to a seperate directory
Mischback Mar 26, 2020
a04ccb1
Renamed project to config
Mischback Mar 31, 2020
fdac3da
Moved the WSGI file to its own directory
Mischback Mar 31, 2020
cd5a336
Docker build process working
Mischback Mar 31, 2020
31053b8
Make Docker-based images work again
Mischback Mar 31, 2020
abb629b
Update manage.py
Mischback Apr 3, 2020
a1d809d
Update Makefile to be consistent with tox.ini
Mischback Apr 3, 2020
fe9432d
Moved/updated the wsgi interface
Mischback Apr 3, 2020
5ec544d
Updated Docker-based deployment files to use new wsgi location
Mischback Apr 3, 2020
ecf16b6
Added asgi.py
Mischback Apr 3, 2020
2ab24b2
Minor fix in config.settings.common
Mischback Apr 5, 2020
dd30df6
Get rid of docker-specific settings
Mischback Apr 5, 2020
d070a09
Made DJANGO_SETTINGS_MODULE configurable
Mischback Apr 5, 2020
7755bcc
Drop support for Python2.7
Mischback Apr 5, 2020
b7a883c
Merge branch 'project-structure' into feature/docker
Mischback Apr 5, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# experimental .dockerignore

# do NOT include the util directory
util

# do NOT include the provided deployment-related files
deploy
# but DO include the production-related scripts/config files that are used
# inside of the images
!deploy/Docker/bin/*
!deploy/Docker/django/entrypoint_django.sh
!deploy/Docker/django/gunicorn_conf.py
!deploy/Docker/django/run_gunicorn.sh
!deploy/Docker/nginx/nginx.conf
!deploy/Docker/nginx/entrypoint_nginx.sh

# do NOT include the documentation
# TODO: the original doc-folder of django-project-skeleton should be removed
# during initialisation of the project. On the other hand, there could be
# project specific documentation. However, this should be excluded from any
# image.
docs

# inside of the images, only the compiled requirements files with the '.txt'
# extension are used. No need to include the source files.
requirements/*.in

# utility files/directories of the repository should not be included
**/.git
**/.tox
**/.dockerignore
**/.editorconfig
**/.gitignore
**/.travis.yml
**/Makefile
**/README*
**/tox.ini

# do not include any samples
**/*.sample

# do NOT track Python compilation stuff
*.py[cod]
**/__python__
**/__pycache__

# TODO: .gitignore excludes compiled language files. Is it safe to exclude the
# uncompiled language files for 'production'?
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ coverage_html
*.mo
*.pot

# I started relying on putting temporary notes into TODO files
*.todo
# do NOT track environment files that are used for docker-compose, but do
# include the sample
deploy/Docker/env.*
!deploy/Docker/env.sample
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ language: python

# listing the Python versions to be tested
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
Expand Down
97 changes: 76 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1,89 @@
.SILENT:
.PHONY: all clean current doc doc-srv serve tox
.PHONY: clean init tree \
docker/build docker/build-context .docker/build-context

# Docker command
DOCKER_CMD := $(shell which docker)

all:
echo ""
echo " clean Removes all temporary files"
echo " current Runs the tox-environment for the current development"
echo " doc Builds the documentation using 'Sphinx'"
echo " doc-srv Serves the documentation on port 8082 (and automatically builds it)"
echo " serve Runs the Django development server on port 8080"
echo " tox Runs complete tox test"
echo ""
# Docker compose command
DOCKER_COMPOSE_CMD := $(shell which docker-compose)

# Docker related testing is performed by using tox:
# - an environment is used to setup a testing project (docker-testing)
# - the project is setup in the temporary directory, thus this step is
# performed by every run
# - the Docker build is triggered using the corresponding Makefile
# Makefile.deployment
# - this Makefile will automatically tag the created image
# - to start the image, this tagging has to be reproduced here
#
# During project setup, this variable is set to the project's name.
# The described testing process will use 'dpstest' as the project's name
DPS_BUILD_NAME_PREFIX := "dpstest"
# While the image is build, the git commit's sha1 hash is used to tag the image
# Additionally, 'latest' is applied to the image aswell.
# In order to run the image, we rely on the 'latest' build.
DPS_BUILD_ID := "latest"

# deletes all temporary files created by Django

# deletes all temporary and unwanted files
clean:
# clean temporary Python files
find . -iname "*.pyc" -delete
find . -iname "__pycache__" -delete
# During development of django-project-skeleton, compiled requirement
# files are needed at some points, but the (compiled) requirements should
# not be included into version control of the skeleton.
# However, once the repository is fetched and used as a template for
# Django's startproject, the compiled requirements *should* be included
# into version control, thus, they can not simply included in a .gitignore.
rm requirements/common.txt
rm requirements/production.txt
rm configs/Docker/env.production

init:
# TODO: Include some output to this function
# create the final version of different files by removing the '.template' suffix
mv ./deploy/apache2_vhost.sample.template ./deploy/apache2_vhost.sample
# switching the tox configuration file
mv ./util/init/tox.ini.template ./tox.ini
# switching the Makefile **should** be the last step
mv ./util/init/Makefile.template ./Makefile

deploy/Docker/env.production:
echo "Initializing environment file for production..."
cp deploy/Docker/env.sample deploy/Docker/env.production
sed -i "s/#DPS_DJANGO_SECRET_KEY=/DPS_DJANGO_SECRET_KEY=$(shell ./util/bin/generate_secret_key.sh)/" deploy/Docker/env.production

docker/build: deploy/Docker/env.production
tox -q -e docker-testing

docker/build-context:
sudo $(MAKE) .docker/build-context

docker/images:
sudo $(MAKE) .docker/images

docker/run: docker/build
sudo $(MAKE) .docker/run

current:
tox -q -e util
run: docker/run

doc:
tox -q -e doc
tree:
tree -a -I ".git|.tox|docs|run" --dirsfirst -C | less -r

doc-srv: doc
tox -q -e doc-srv
.docker/build-context:
echo " \
FROM busybox\n \
COPY . /build-context\n \
WORKDIR /build-context\n \
CMD find ." | \
$(DOCKER_CMD) build -t "$(DPS_BUILD_NAME_PREFIX)/build-context:latest" -f- . && \
$(DOCKER_CMD) container run --rm "$(DPS_BUILD_NAME_PREFIX)/build-context:latest"

serve:
tox -q -e run
.docker/images:
$(DOCKER_CMD) images

tox:
tox -q
.docker/run:
DPS_BUILD_NAME_PREFIX=$(DPS_BUILD_NAME_PREFIX) DPS_BUILD_ID=$(DPS_BUILD_ID) \
$(DOCKER_COMPOSE_CMD) -f deploy/Docker/docker-compose.yml up
File renamed without changes.
File renamed without changes.
156 changes: 156 additions & 0 deletions config/settings/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Python imports
import logging
import os
import sys

logger = logging.getLogger(__name__)


# ##### PATH CONFIGURATION ################################

# fetch Django's project directory
DJANGO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# fetch the project_root
PROJECT_ROOT = os.path.dirname(DJANGO_ROOT)

# the name of the whole site
SITE_NAME = os.path.basename(DJANGO_ROOT)

# collect static files here
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'run', 'static')

# collect media files here
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'run', 'media')

# look for static assets here
STATICFILES_DIRS = [
os.path.join(PROJECT_ROOT, 'static'),
]

# look for templates here
# This is an internal setting, used in the TEMPLATES directive
PROJECT_TEMPLATES = [
os.path.join(PROJECT_ROOT, 'templates'),
]

# add apps/ to the Python path
sys.path.append(os.path.normpath(os.path.join(PROJECT_ROOT, 'apps')))


# ##### APPLICATION CONFIGURATION #########################

# set the project's default timezone
TIME_ZONE = os.environ.get('DPS_TIMEZONE', 'Etc/UTC')

# these are the apps
DEFAULT_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

# Middlewares
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# template stuff
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': PROJECT_TEMPLATES,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages'
],
},
},
]

# The WSGI application to be used by Django's internal servers.
# Please note, Django's 'runserver' should **not** be used in production
# environments.
# If set to 'None', 'django.core.wsgi.get_wsgi_application()' will be used to
# determine the WSGI application.
WSGI_APPLICATION = os.environ.get('DPS_DJANGO_WSGI_APP', None)

# the root URL configuration
ROOT_URLCONF = '{}.urls'.format(SITE_NAME)

# the URL for static files
STATIC_URL = os.environ.get('DPS_STATIC_URL', '/static/')

# the URL for media files
MEDIA_URL = os.environ.get('DPS_DJANGO_MEDIA_URL', '/media/')

# adjust the minimal login
LOGIN_URL = 'core_login'
LOGIN_REDIRECT_URL = os.environ.get('DPS_DJANGO_LOGIN_REDIRECT_URL', '/')
LOGOUT_REDIRECT_URL = os.environ.get('DPS_DJANGO_LOGOUT_REDIRECT_URL', 'core_login')

# Internationalization
USE_I18N = False

# uncomment the following line to include i18n
# from .i18n import *


# ##### SECURITY CONFIGURATION ############################

# We store the secret key here
# The required SECRET_KEY is fetched at the end of this file
SECRET_FILE = os.path.normpath(os.path.join(PROJECT_ROOT, 'run', 'SECRET.key'))

# these persons receive error notification
ADMINS = (
('your name', 'your_name@example.com'),
)
MANAGERS = ADMINS


# ##### DEBUG CONFIGURATION ###############################
DEBUG = False


logger.debug('Trying to fetch SECRET_KEY from the environment...')
SECRET_KEY = os.environ.get('DPS_DJANGO_SECRET_KEY')
if SECRET_KEY is None:
logger.debug('Could not find key in the environment!')

logger.debug('Trying to read SECRET_KEY from SECRET_FILE...')
try:
SECRET_KEY = open(SECRET_FILE).read().strip()
logger.info('Read SECRET_KEY from SECRET_FILE.')
except IOError:
logger.debug('Could not open SECRET_FILE ({})!'.format(SECRET_FILE))

try:
from django.utils.crypto import get_random_string
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!$%&()=+-_'
SECRET_KEY = get_random_string(50, chars)
with open(SECRET_FILE, 'w') as f:
f.write(SECRET_KEY)

logger.info('Generated a new SECRET_KEY and stored it in SECRET_FILE ({})!'.format(SECRET_FILE))
except IOError:
logger.exception('Could not open SECRET_FILE ({}) for writing!'.format(SECRET_FILE))
raise Exception('Could not open {} for writing!'.format(SECRET_FILE))
else:
logger.info('Fetched SECRET_KEY from environment.')
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
# Python imports
from os.path import join
import os

# project imports
# fetch the common settings
from .common import *

# uncomment the following line to include i18n
# from .i18n import *


# ##### DEBUG CONFIGURATION ###############################
DEBUG = True
# ##### APPLICATION CONFIGURATION #########################

# allow all hosts during development
ALLOWED_HOSTS = ['*']

# adjust the minimal login
LOGIN_URL = 'core_login'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = 'core_login'
INSTALLED_APPS = DEFAULT_APPS


# ##### DATABASE CONFIGURATION ############################
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': join(PROJECT_ROOT, 'run', 'dev.sqlite3'),
'NAME': os.path.join(PROJECT_ROOT, 'run', 'dev.sqlite3'),
}
}

# ##### APPLICATION CONFIGURATION #########################

INSTALLED_APPS = DEFAULT_APPS
# ##### DEBUG CONFIGURATION ###############################
DEBUG = True
5 changes: 2 additions & 3 deletions project_name/settings/i18n.py → config/settings/i18n.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Python imports
from os.path import join
import os

# Django imports
from django.utils.translation import ugettext_lazy as _
Expand All @@ -10,7 +10,6 @@
# ##### INTERNATIONALIZATION ##############################

LANGUAGE_CODE = 'de'
TIME_ZONE = 'Europe/Berlin'

# Internationalization
USE_I18N = True
Expand All @@ -29,7 +28,7 @@

# Look for translations in these locations
LOCALE_PATHS = (
join(PROJECT_ROOT, 'locale'),
os.path.join(PROJECT_ROOT, 'locale'),
)

# Inject the localization middleware into the right position
Expand Down
Loading