My Python development Dockerfile setup

I use Docker for almost each of my projects and configuring development config may be a pain. Finally, I got a working, easy to use and easy to understand setup. I know it's not perfect and may contain some obvious pitfalls, but still - it works and I know how to deal with it! :)

In most of my projects I meet similar service requirements:

  • A Python container
  • A database (preferably Postgres)
  • A mail service

Using Docker, getting such configuration running on every machine is available in literally few seconds (apart from downloading images...)

Below you'll find a working configuration for a Django project with pipenv as a dependency manager. It is a matter of few lines to get rid of Django-related config and keep as pure Python setup.

Dockerfile:

FROM python:3.7

ENV PYTHONUNBUFFERED 1

# required for Django: ./manage.py compilemessages
RUN apt update && \
apt install gettext -y

# Create our working directory inside the image
RUN mkdir -p /app
WORKDIR /app

# Install packages
COPY ./Pipfile ./Pipfile
COPY ./Pipfile.lock ./Pipfile.lock
RUN pip install pipenv

# Copy our packages
COPY ./src /app
RUN pipenv install --system --deploy

# IPDB, for tinkering inside ;)
RUN pip install ipdb

# Entrypoint to wait for postgres
# May be removed if not used
COPY ./docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Start the development command
COPY ./docker/start-dev.sh /start-dev.sh
RUN chmod +x /start-dev.sh

EXPOSE 8000

ENTRYPOINT ["/entrypoint.sh"]
CMD ["/start-dev.sh"]

And a docker-compose file, to see the final result

version: '3'

volumes:
project_pgdata: {}

networks:
project:
driver: bridge

services:
api:
build:
context: .
dockerfile: ./docker/Dockerfile
depends_on:
- postgres
- mailhog
volumes:
- ./src:/app
- ./uploads:/uploads
ports:
- "8000:8000"
env_file:
- .env
networks:
- project

postgres:
image: postgres:10.1
volumes:
- project_pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
env_file:
- .env
networks:
- project

mailhog:
image: mailhog/mailhog:v1.0.0
ports:
- "8025:8025"
networks:
- project

As you can see, the file is pretty straightforward. I keep my docker-related data inside the docker directory. I also use mailhog as a quick email server.

If you're interested in what I keep in my start-dev.sh file, take a look:

#!/bin/bash
python manage.py migrate
python manage.py compilemessages
python manage.py runserver 0.0.0.0:8000

As for the waitforpostgres.sh script, there are lots of implementations for it, just pick to one that suits you.