One way to deploy python, django and friends.

Table of contents

No heading

No headings in the article.

My journey into the realm of docker started quite a while back. I was in a hurry. I needed something that just worked and I needed to deliver it right now - or preferably the day before.

So, naturally, I hacked together a build and deploy system. ...And then I just kept on using it.

Templates are a honking great idea

config/templates/
  docker-compose-template.yml
  docker-entrypoint-template
  Dockerfile-template
  gunicorn-template.conf
  nginx-template.conf
  nginx-template-local.conf
  project-variables-template
  tasks-template.py
  template-envs

And what do they look like? Basically like this:

File: docker-compose-template.yml

version: '3.7'
services:
.
.
.
  ${APPSERVICE_NAME}:
    ${APPSERVICE_CONTAINER_NAME}
    entrypoint: /opt/services/${VOLUME_PREFIX}${VOLUME_NAME}/src/docker-entrypoint.sh
    command: gunicorn -c config/gunicorn/conf.py${RELOAD}--chdir ${APP_NAME} --bind :${APP_PORT} ${APP_NAME}.wsgi:application
    restart: unless-stopped
    build: .
    stdin_open: true
    tty: true
    security_opt:
      - seccomp:unconfined
    ports:
      - "${APP_PORT}"
    env_file:
      - project-variables.env
    volumes:
      - .:/opt/services/${VOLUME_PREFIX}${VOLUME_NAME}/src
      - ${VOLUME_PREFIX}static_volume:/opt/services/${VOLUME_PREFIX}${VOLUME_NAME}/static
      - ${VOLUME_PREFIX}media_volume:/opt/services/${VOLUME_PREFIX}${VOLUME_NAME}/media
    networks:
      default:
    depends_on:
      - ${MEMCACHED_NAME}
      - ${DBSERVICE_NAME}

template-envs provides the variables for substitution. This file is for the most part not checked into the VCS. If you do happen to check this file in you should take care to change the secrets in production.

And to write out the docker-compose.yaml?

Contents of generate-deploy-files.sh
  source ./config/templates/template-envs
  .
  .
  .
  envsubst < "./config/templates/docker-compose-template.yml" > "docker-  compose.yml"
  .
  .
  envsubst '${WORKER_PROCESSES},${WORKER_RLIMIT_NOFILE},${WORKER_CONNECTIONS}' < "./config/templates/nginx-template.conf" > "./config/nginx/nginx.conf"
.
.

Finally, I've added a Makefile so that I don't have to type out the various build and clean commands.

Contents of Makefile
  #! /bin/bash
  .
  .
  define dev
        ./generate-deploy-files -r reload -d DEBUG
        docker-compose up -d --build $(c)
  endef
  .
  .
  debug: 
     $(write_rev)
     echo "debug" >> ${rev_path}/revision.txt
     $(dev)
  .
  .
  .

So, there it is - basically. Super easy, super flexible system that works well for single host environments. Maybe some day I'll extract the files out into a repo by them selves.