Основи Python и Django. / Django з використанням Docker. / Використовуємо Docker із Django.

Використовуємо Docker з Django та PostgreSQL.

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

django-admin startproject prj

створюємо Dockerfile з образом під пітон.

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