После установки пустого проекта джанго
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
Изменяем 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