Теперь создадим образ докера для создания контейнера с Django.
В данном примере будет использоваться мульти-образ для экономии места. builder - это временный образ с помощью которого будут созданы бинарные файлы библиотек Python. После создания образа builder с него будут скопированы файлы в наш основной образ.
Создадим файл app/Dockerfile.prod:
###########
# BUILDER #
###########
FROM python:3.12.0-alpine as builder
WORKDIR /usr/src/app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# установка зависимостей
RUN apk update \
&& apk add postgresql-dev gcc python3-dev musl-dev
RUN pip install --upgrade pip
# установка зависимостей
COPY ./requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt
#########
# FINAL #
#########
FROM python:3.12.0-alpine
# создаем директорию для пользователя
RUN mkdir -p /home/app
# создаем отдельного пользователя и его группы
RUN addgroup -S app && adduser -S app -G app
# создание директории для проекта Django
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
# установка зависимостей
RUN apk update && apk add libpq
COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
RUN pip install --no-cache /wheels/*
# копирование entrypoint-prod.sh
COPY ./entrypoint.prod.sh $APP_HOME
# копирование проекта Django
COPY . $APP_HOME
# смена владельца файлов и директорий проекта Django, на пользователя app
RUN chown -R app:app $APP_HOME
# изменение рабочего пользователя
USER app
# установим права и запустим скрипт проверки запуска БД
RUN chmod +x /home/app/web/entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
В образе мы создали пользователя app и его группу app. Это делается для того, что бы не использовать пользователя root, который используется по умолчанию в контейнерах Docker.
Создадим файл entrypoint.prod.sh в папке app, рядом с Dockerfile.prod
#!/bin/sh
if [ "$DATABASE" = "postgres" ]
then
echo "Postgres еще не запущен..."
# Проверяем доступность хоста и порта
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 10
done
echo "PostgreSQL запущен"
fi
exec "$@"
Данный файл необходим чтобы проверить работоспособность PostgreSQL перед применением миграции и запуском сервера разработки Django.
Изменим файл docker-compose.prod.yml, что бы он использовал новый файл - Dockerfile.prod:
version: '3.8'
services:
web:
# Берем Dockerfile из каталога app
build:
context: ./app
dockerfile: Dockerfile.prod
# Запускаем сервер gunicorn
command: gunicorn core.wsgi:application --bind 0.0.0.0:8000
# Открываем порт 8000 внутри и снаружи
ports:
- 8000:8000
# Файл содержащий переменные для контейнера
env_file:
- .env.prod
# Дожидаемся запуска контейнера db и memcached
depends_on:
- db
- memcached
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=book_django
- POSTGRES_PASSWORD=pass_book_django
- POSTGRES_DB=book_django
memcached:
image: memcached:1.6.21
ports:
- 11211:11211
volumes:
postgres_data:
Протестируем:
docker-compose -f docker-compose.prod.yml down -v
docker-compose -f docker-compose.prod.yml up -d --build
docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput
И откроем в браузере http://127.0.0.1:8000, мы видим что все прекрасно работает через Gunicorn.