Commit 6069cdde authored by William Tucker's avatar William Tucker
Browse files

Removed or refactored images to simplify deployment

parent ac3218b6
Loading
Loading
Loading
Loading
Loading

images/auth-service/Dockerfile

deleted100644 → 0
+0 −49
Original line number Diff line number Diff line
#####
## Docker image for the Django auth service
#####

ARG ESGF_REPOSITORY_BASE=esgfdeploy
ARG ESGF_IMAGES_VERSION=latest
ARG GIT_REPOSITORY=https://github.com/cedadev/django-auth-service.git
ARG GIT_VERSION=b5f8c31817a1373828470b0899265be69455a6ec

FROM ${ESGF_REPOSITORY_BASE}/python-build:${ESGF_IMAGES_VERSION} as python-build

FROM ${ESGF_REPOSITORY_BASE}/conda:${ESGF_IMAGES_VERSION}

USER root

# Install gunicorn server, whitenoise to handle static files and 
# django-flexi-settings for smart handling of settings
RUN pip install --no-cache-dir \
      'gunicorn==20.0.4' \
      'django-flexi-settings==0.1.1' \
      'whitenoise==5.2.0'

# Install gunicorn config file
COPY gunicorn.conf.py /etc/gunicorn/conf.py
COPY wsgi-serve.sh /usr/local/bin/

# Configure Django to use the flexi settings module
ENV DJANGO_SETTINGS_MODULE flexi_settings.settings
# Install the default settings
ENV DJANGO_FLEXI_SETTINGS_ROOT /etc/django/settings.py
COPY conf /etc/django
# Make sure the settings directory exists
RUN mkdir -p /etc/django/settings.d

# Install init scripts and serving script
COPY django-serve.sh /usr/local/bin/

# Use ONBUILD instructions to install and configure the application
COPY --from=python-build /build/wheelhouse /build/wheelhouse
#   Install the wheels that we copied
RUN pip install --no-deps /build/wheelhouse/*.whl
#   Install the app settings
COPY settings.d/* /etc/django/settings.d/
#   Make sure to run as the ESGF user
USER $ESGF_UID

# By default, serve the Django application on port 8080
EXPOSE 8080
CMD ["/usr/local/bin/django-serve.sh"]
+0 −125
Original line number Diff line number Diff line
"""
Default settings, including security best practices.
"""

import os

from django.core.management.utils import get_random_secret_key


# By default, don't run in DEBUG mode
DEBUG = False

# In a Docker container, ALLOWED_HOSTS is always '*' - let the proxy worry about hosts
ALLOWED_HOSTS = ['*']

# Make sure Django interprets the script name correctly if set
if 'SCRIPT_NAME' in os.environ:
    FORCE_SCRIPT_NAME = os.environ['SCRIPT_NAME']

# Security settings
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
X_FRAME_OPTIONS = 'DENY'
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# Set a default random secret key
# This can be overridden by files included later if desired
SECRET_KEY = get_random_secret_key()

# All logging should go to stdout/stderr to be collected
import logging
LOG_FORMAT = '[%(levelname)s] [%(asctime)s] [%(name)s:%(lineno)s] [%(threadName)s] %(message)s'
LOGGING = {
    'version' : 1,
    'disable_existing_loggers' : False,
    'formatters' : {
        'default' : {
            'format' : LOG_FORMAT,
        },
    },
    'filters' : {
        # Logging filter that only accepts records with a level < WARNING
        # This allows us to log level >= WARNING to stderr and level < WARNING to stdout
        'less_than_warning' : {
            '()': 'django.utils.log.CallbackFilter',
            'callback': lambda record: record.levelno < logging.WARNING,
        },
    },
    'handlers' : {
        'stdout' : {
            'class' : 'logging.StreamHandler',
            'stream' : 'ext://sys.stdout',
            'formatter' : 'default',
            'filters': ['less_than_warning'],
        },
        'stderr' : {
            'class' : 'logging.StreamHandler',
            'stream' : 'ext://sys.stderr',
            'formatter' : 'default',
            'level' : 'WARNING',
        },
    },
    'loggers' : {
        '' : {
            'handlers' : ['stdout', 'stderr'],
            'level' : 'INFO',
            'propogate' : True,
        },
    },
}

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

# By default, no databases are defined
DATABASES = {}

# Authentication settings
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# IMPORTANT: CookieStorage (and hence FallbackStorage, which is the default) interacts
#            badly with Chrome's prefetching, causing messages to be rendered twice
#            or not at all...!
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'

# Default internationalization settings
LANGUAGE_CODE = 'en-gb'
TIME_ZONE = 'Europe/London'
USE_I18N = True
USE_L10N = True
USE_TZ = True

# Static files (CSS, JavaScript, Images)
# Make sure to include the WSGI script name in the static URL
STATIC_URL = '{}/static/'.format(os.environ.get('SCRIPT_NAME', ''))
STATIC_ROOT = '/var/django/staticfiles'
+0 −20
Original line number Diff line number Diff line
"""
Root settings file

Includes settings files from a sibling directory called settings.d.
"""

import os
from pathlib import Path

from flexi_settings import include, include_dir


base_dir = Path(__file__).resolve().parent

# First, include the defaults
include(base_dir / "defaults.py")
# Then include the user settings
include_dir(base_dir / "settings.d")
# Always include the whitenoise settings to configure static files
include(base_dir / "whitenoise.py")
+0 −18
Original line number Diff line number Diff line
"""
Modify settings to serve static files using whitenoise.
"""

_SECURITY_MIDDLEWARE = 'django.middleware.security.SecurityMiddleware'
_WHITENOISE_MIDDLEWARE = 'whitenoise.middleware.WhiteNoiseMiddleware'

# Make sure MIDDLEWARE is a list, not a tuple
MIDDLEWARE = list(globals().get('MIDDLEWARE', []))
# As per the docs, inject the whitenoise middleware after the security middleware
try:
    index = MIDDLEWARE.index(_SECURITY_MIDDLEWARE)
except ValueError:
    index = -1
MIDDLEWARE.insert(index + 1, _WHITENOISE_MIDDLEWARE)

# Use the whitenoise static file storage for caching, compression etc.
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
+0 −14
Original line number Diff line number Diff line
#!/usr/bin/bash

# Extract the WSGI application from the Django settings
echo "[info] Extracting WSGI application from Django settings"
# The Django WSGI_APPLICATION setting has all dots, whereas gunicorn expects "py.mod:var"
# So we need to replace the right-most dot with a colon
wsgi_application_script="
from django.conf import settings
print(settings.WSGI_APPLICATION[::-1].replace('.', ':', 1)[::-1])
"
WSGI_APPLICATION="$(django-admin shell -c "$wsgi_application_script")"

echo "[info] Running WSGI application $WSGI_APPLICATION"
exec /usr/local/bin/wsgi-serve.sh $WSGI_APPLICATION
Loading