Unverified Commit d73a4f26 authored by Thom Wiggers's avatar Thom Wiggers 📐
Browse files

Get docker ready for production

parent badacdb9
.gitignore
\ No newline at end of file
# Note that the syntax of this file is very different from .gitignore
# Notably, all paths are from the Dockerfile's location (e.g. specifying a
# single file name `foo` will not ignore `bar/baz/foo`).
# Furthermore, note that using `**` in a path appears to be broken at the
# moment of writing: https://github.com/docker/docker-py/issues/1117
# Be very careful about pushing locally built images to (semi)-public places.
# When in doubt, consider building from a fresh clone of the repository.
website/media
website/static
website/db.sqlite3
website/thaliawebsite/settings/localsettings.py
# These files would not be copied, but increase the size of the build context
.git
.tox
FROM python:3.5-alpine FROM python:3.5-alpine
MAINTAINER Thom Wiggers <thom@thomwiggers.nl> MAINTAINER Thom Wiggers <thom@thomwiggers.nl>
LABEL version=1.0
LABEL description="Contains the Thaliawebsite Django application" LABEL description="Contains the Thaliawebsite Django application"
# Try to keep static operation on top to maximise Docker cache utilisation # Try to keep static operation on top to maximise Docker cache utilisation
...@@ -9,19 +8,17 @@ LABEL description="Contains the Thaliawebsite Django application" ...@@ -9,19 +8,17 @@ LABEL description="Contains the Thaliawebsite Django application"
ENV DJANGO_PRODUCTION 1 ENV DJANGO_PRODUCTION 1
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED 1
RUN mkdir /concrexit
# Create log dir # Create log dir
RUN mkdir /log/ RUN mkdir /concrexit/log/
RUN touch /log/uwsgi.log RUN touch /concrexit/log/uwsgi.log
RUN chown -R 33:33 /concrexit
# Create app directory # Create app directory
RUN mkdir -p /usr/src/app RUN mkdir -p /usr/src/app
# Create entry points
WORKDIR /usr/local/bin
COPY resources/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY resources/entrypoint_production.sh /usr/local/bin/entrypoint_production.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint_production.sh
# Install dependencies # Install dependencies
RUN apk add --no-cache \ RUN apk add --no-cache \
gettext \ gettext \
...@@ -31,8 +28,10 @@ RUN apk add --no-cache \ ...@@ -31,8 +28,10 @@ RUN apk add --no-cache \
tiff \ tiff \
zlib \ zlib \
freetype \ freetype \
uwsgi \
lcms2 \ lcms2 \
libxml2 \
libxslt \
libffi \
libjpeg-turbo libjpeg-turbo
# Install build deps # Install build deps
...@@ -44,19 +43,40 @@ RUN apk add --no-cache --virtual .builddeps \ ...@@ -44,19 +43,40 @@ RUN apk add --no-cache --virtual .builddeps \
freetype-dev \ freetype-dev \
lcms2-dev \ lcms2-dev \
libwebp-dev \ libwebp-dev \
libxml2-dev \
libxslt-dev \
libffi-dev \
linux-headers \
git \
postgresql-dev postgresql-dev
# Install mongodb separately because it's in edge still
RUN echo http://dl-4.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories && \
apk add --no-cache libsass
WORKDIR /usr/src/app WORKDIR /usr/src/app
# install python requirements # install python requirements
COPY requirements.txt /usr/src/app/ COPY requirements.txt /usr/src/app/
COPY production-requirements.txt /usr/src/app/ COPY production-requirements.txt /usr/src/app/
COPY migration-requirements.txt /usr/src/app/
COPY dev-requirements.txt /usr/src/app/
RUN pip install --no-cache-dir \ RUN pip install --no-cache-dir \
-r requirements.txt \ -r requirements.txt \
-r production-requirements.txt -r production-requirements.txt \
-r migration-requirements.txt \
-r dev-requirements.txt
RUN apk del .builddeps RUN apk del .builddeps
# Create entry points
WORKDIR /usr/local/bin
COPY resources/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY resources/entrypoint_production.sh /usr/local/bin/entrypoint_production.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint_production.sh
# copy app source # copy app source
WORKDIR /usr/src/app
COPY website /usr/src/app/ COPY website /usr/src/app/
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
......
...@@ -2,9 +2,12 @@ version: '2' ...@@ -2,9 +2,12 @@ version: '2'
services: services:
postgres: postgres:
image: postgres image: postgres
volumes:
- /var/lib/postgresql/
environment: &postgresvars environment: &postgresvars
POSTGRES_DB: thalia POSTGRES_DB: thalia
web: web:
image: registry.gitlab.com/thaliawww/concrexit
build: . build: .
command: runserver 0.0.0.0:8000 command: runserver 0.0.0.0:8000
ports: ports:
...@@ -13,7 +16,15 @@ services: ...@@ -13,7 +16,15 @@ services:
- postgres - postgres
volumes: volumes:
- ./website:/usr/src/app - ./website:/usr/src/app
- /concrexit/media
- /concrexit/static
environment: environment:
<<: *postgresvars <<: *postgresvars
DJANGO_DEBUG: 'True' DJANGO_DEBUG: 'True'
DJANGO_POSTGRES_HOST: postgres DJANGO_POSTGRES_HOST: postgres
MIGRATION_KEY: ${CONCREXIT_MIGRATION_KEY}
volumes:
concrexit-media:
driver: local
concrexit-static:
driver: local
...@@ -8,15 +8,19 @@ until psql -h "$DJANGO_POSTGRES_HOST" -U "postgres" -c '\l'; do ...@@ -8,15 +8,19 @@ until psql -h "$DJANGO_POSTGRES_HOST" -U "postgres" -c '\l'; do
done done
>&2 echo "PostgreSQL is up" >&2 echo "PostgreSQL is up"
chown -R 33:33 /concrexit/
cd /usr/src/app cd /usr/src/app
>&2 echo "Running site with uwsgi" >&2 echo "Running site with uwsgi"
uwsgi --chdir /usr/src/app \ uwsgi --chdir /usr/src/app \
--socket :8000 \ --socket :8000 \
--threads 2 \ --uid 33 \
--processes 4 \ --gid 33 \
--threads 5 \
--processes 5 \
--module thaliawebsite.wsgi:application \ --module thaliawebsite.wsgi:application \
--lazy-app \
--harakiri 20 \ --harakiri 20 \
--master \
--max-requests 5000 \ --max-requests 5000 \
--vacuum \ --vacuum \
--logto '/log/uwsgi.log' --logto '/concrexit/log/uwsgi.log'
...@@ -2,10 +2,18 @@ ...@@ -2,10 +2,18 @@
Django settings for thaliawebsite project. Django settings for thaliawebsite project.
Docker version Docker version
See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
""" """
import os import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.abspath(os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'..', '..'))
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get( SECRET_KEY = os.environ.get(
'DJANGO_SECRET', 'DJANGO_SECRET',
...@@ -16,8 +24,7 @@ DEBUG = os.environ.get('DJANGO_DEBUG') == 'True' ...@@ -16,8 +24,7 @@ DEBUG = os.environ.get('DJANGO_DEBUG') == 'True'
ALLOWED_HOSTS = os.environ.get('DJANGO_HOSTS', '').split(',') ALLOWED_HOSTS = os.environ.get('DJANGO_HOSTS', '').split(',')
ROOT_URLCONF = 'thaliawebsite.urls' # Database settings
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql', 'ENGINE': 'django.db.backends.postgresql',
...@@ -28,26 +35,24 @@ DATABASES = { ...@@ -28,26 +35,24 @@ DATABASES = {
'PORT': 5432, 'PORT': 5432,
} }
} }
# Persistent database connections
CONN_MAX_AGE = '60'
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/dev/howto/static-files/ # https://docs.djangoproject.com/en/dev/howto/static-files/
# Where to store uploaded files # Where to store uploaded files
MEDIA_ROOT = os.path.join('/', 'media') MEDIA_ROOT = '/concrexit/media'
MEDIA_URL = '/media/' # Public is included by the db fields MEDIA_URL = '/media/' # Public is included by the db fields
SENDFILE_BACKEND = 'sendfile.backends.development' SENDFILE_BACKEND = 'sendfile.backends.development'
STATIC_URL = '/static/' STATIC_URL = '/static/'
STATIC_ROOT = '/static' STATIC_ROOT = '/concrexit/static'
COMPRESS_ENABLED = True
COMPRESS_PRECOMPILERS = ( if not DEBUG:
('text/x-scss', 'django_libsass.SassCompiler'), COMPRESS_OFFLINE = True
)
COMPRESS_CSS_FILTERS = ['compressor.filters.css_default.CssAbsoluteFilter',
'compressor.filters.cssmin.rCSSMinFilter']
PASSWORD_HASHERS = [ PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher', 'django.contrib.auth.hashers.Argon2PasswordHasher',
...@@ -58,3 +63,52 @@ PASSWORD_HASHERS = [ ...@@ -58,3 +63,52 @@ PASSWORD_HASHERS = [
] ]
WIKI_API_KEY = os.environ.get('WIKI_API_KEY', 'changeme') WIKI_API_KEY = os.environ.get('WIKI_API_KEY', 'changeme')
MIGRATION_KEY = os.environ.get('MIGRATION_KEY')
if os.environ.get('DJANGO_SSLONLY'):
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# Use caching template loader
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.template.context_processors.media',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'partners.context_processors.showcased_partners',
],
'loaders': [
('django.template.loaders.cached.Loader', [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
]),
],
},
},
]
# ADMINS
ADMINS = [('Technicie', 'www@thalia.nu')]
# Email backend
if os.environ.get('DJANGO_EMAIL_HOST'):
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.environ['DJANGO_EMAIL_HOST']
EMAIL_PORT = os.environ['DJANGO_EMAIL_PORT']
EMAIL_HOST_USER = os.environ.get('DJANGO_EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('DJANGO_EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = os.environ.get('DJANGO_EMAIL_USE_TLS', False) == 'True'
EMAIL_USE_SSL = os.environ.get('DJANGO_EMAIL_USE_SSL', False) == 'True'
EMAIL_TIMEOUT = 10
# Secure headers
X_FRAME_OPTIONS = 'DENY'
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
...@@ -74,6 +74,7 @@ MIDDLEWARE = [ ...@@ -74,6 +74,7 @@ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', 'corsheaders.middleware.CorsMiddleware',
'django.middleware.http.ConditionalGetMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
...@@ -84,6 +85,9 @@ MIDDLEWARE = [ ...@@ -84,6 +85,9 @@ MIDDLEWARE = [
ROOT_URLCONF = 'thaliawebsite.urls' ROOT_URLCONF = 'thaliawebsite.urls'
# WARNING
# Also update this in production.py!!!
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
...@@ -202,6 +206,8 @@ COMPRESS_CSS_FILTERS = ['compressor.filters.css_default.CssAbsoluteFilter', ...@@ -202,6 +206,8 @@ COMPRESS_CSS_FILTERS = ['compressor.filters.css_default.CssAbsoluteFilter',
# Precompiler settings # Precompiler settings
STATIC_PRECOMPILER_LIST_FILES = True STATIC_PRECOMPILER_LIST_FILES = True
# Default FROM email
DEFAULT_FROM_EMAIL = 'noreply@thalia.nu'
# Newsletter settings # Newsletter settings
NEWSLETTER_FROM_ADDRESS = 'nieuwsbrief@thalia.nu' NEWSLETTER_FROM_ADDRESS = 'nieuwsbrief@thalia.nu'
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment