Используем Docker с Django и PostgreSQL.

После установки пустого проекта джанго

django-admin startproject prj

создаем Dockerfile c образом под питон.

FROM python:3.6 AS python36
ENV PYTHONUNBUFFERED 1
RUN mkdir /app
WORKDIR /app
RUN apt update
RUN apt -y install libpq-dev netcat
COPY requirements.txt /app
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip install -r requirements.txt
RUN mkdir /entry
COPY entrypoint.sh /entry
ENTRYPOINT ["/entry/entrypoint.sh"]

Создаем файл entrypoint.sh для запуска миграции когда будет доступно подключение к БД.

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

python manage.py flush --no-input
python manage.py migrate

exec "$@"

nc -z $SQL_HOST $SQL_PORT - пытается соединится (тут довольно часто) по ИП и порту.

В entrypoint обычно ложат то что разработчиками не меняется.

Создадим файл .env.dev для определения переменных окружения.

DEBUG=1
DATABASE=postgres
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_DATABASE=imaginary
SQL_USER=postgres
SQL_PASSWORD=123
SQL_HOST=db
SQL_PORT=5432

Их мы потом будем “вталкивать” в настройки проекта (settings.py) как-то так:

import os
DEBUG = os.getenv('DEBUG', 'True')
DJANGO_ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '[*]')
DATABASE = os.getenv('DATABASE', 'sqlite3')
SQL_DATABASE = os.getenv('SQL_DATABASE', 'imaginary')
SQL_USER = os.getenv('SQL_USER', 'postgres')
SQL_PASSWORD = os.getenv('SQL_PASSWORD', '123')
SQL_PORT = os.getenv('SQL_PORT', '5432')

Создаем сборщик контейнеров в файле docker-compose.yaml.

version: '3.5'
services: 
    django:
        build: .
        restart: always
        ports:
            - 8000:8000
        working_dir: /app
        command: python manage.py runserver 0.0.0.0:8000
        volumes:
            - ./prj:/app
        depends_on:
            - db
        env_file:
            - ./.env.dev

    db:
        restart: always
        image: postgres:latest
        volumes:
            - ./pg_data:/var/lib/postgresql/data/
        environment:
            - POSTGRES_USER=postgres
            - POSTGRES_PASSWORD=1q2w3e
            - POSTGRES_DB=imaginary

Тут у нас пока 2 контейнера под БД и джанго-дев-сервер.

Причем мы настроили БД для хранения данных внутри папки (pg_data) проекта, на случай если вы “грохните” контейнер или образ то данные сохранятся. Поэтому папочку нужно создать.

env_file - тут мы присоединяем файл с переменными окружения.

Поднимаем контейнера.

docker-compose up --build

start page

start page

Изменяем settings.py.

import os
DEBUG = os.getenv('DEBUG', 'True')
DJANGO_ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '[*]')
DATABASE = os.getenv('DATABASE', 'sqlite3')
SQL_DATABASE = os.getenv('SQL_DATABASE', 'imaginary')
SQL_USER = os.getenv('SQL_USER', 'postgres')
SQL_PASSWORD = os.getenv('SQL_PASSWORD', '123')
SQL_HOST = os.getenv('SQL_HOST', 'db')
SQL_PORT = os.getenv('SQL_PORT', '5432')

if DATABASE == 'sqlite3':
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        }
    }
elif DATABASE == 'postgres':

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': SQL_DATABASE,
            'USER': SQL_USER,
            'PASSWORD': SQL_PASSWORD,
            'HOST': SQL_HOST,
            'PORT': SQL_PORT,
        },
    }

Если получаем сообщение о том что база данных не существует, то необходимо удалить и пересобрать контейнеры.

docker-compose down -v   
docker-compose up --build

Запуск контейнеров по одному.

Запускать контейнеры по одному можно командой.

docker-compose run django

Можно создать исполняемй файл и запустить каждый контейнер в отдельном окне терминального менеджера tmux.

Например создадим файл monitor.sh

#!/bin/bash
command -v tmux >/dev/null 2>&1 || { echo >&2 "I require tmux but it's not installed.  Aborting."; exit 1; }

tmux new-session \; \
 split-window -v \; \
 select-pane -t 0 \; \
 send-keys 'docker-compose run db' C-m \; \
 select-pane -t 1 \; \
 send-keys 'docker-compose run django' C-m \; \
 select-pane -t 0 \;

Разбивать терминал можно и по горизонтали.

split-window -h \; select-pane -t 0 \; \

Теперь сделаем его исполняемым.

chmod +x monitor.sh

И запустим.

./monitor.sh

start page