Продвинутые инструкции Dockerfile
На этом последнем этапе мы рассмотрим дополнительные инструкции Dockerfile и рекомендации, которые помогут сделать ваши Docker-образы более безопасными, поддерживаемыми и легкими в использовании. Также мы сосредоточимся на устранении неполадок и проверке каждого шага процесса.
-
В WebIDE снова откройте файл Dockerfile
.
-
Замените его содержимое следующим:
## Стадия сборки
FROM python:3.9-slim AS builder
WORKDIR /app
COPY requirements.txt.
RUN pip install --user --no-cache-dir -r requirements.txt
## Финальная стадия
FROM python:3.9-slim
## Создание не-root пользователя
RUN useradd -m appuser
## Установка curl для проверки здоровья
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
WORKDIR /app
## Динамическое определение версии Python и пути к site-packages
RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && \
SITE_PACKAGES_PATH="/home/appuser/.local/lib/python${PYTHON_VERSION}/site-packages" && \
mkdir -p "${SITE_PACKAGES_PATH}" && \
chown -R appuser:appuser /home/appuser/.local
## Копирование site-packages и бинарников с использованием переменной
COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}"
COPY --from=builder /root/.local/bin /home/appuser/.local/bin
COPY app.py.
ENV PATH=/home/appuser/.local/bin:$PATH
ENV ENVIRONMENT=production
## Установка пользователя для запуска приложения
USER appuser
## Использование ENTRYPOINT с CMD
ENTRYPOINT ["python"]
CMD ["app.py"]
EXPOSE 5000
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:5000/ || exit 1
ARG BUILD_VERSION
LABEL maintainer="Ваше имя <[email protected]>"
LABEL version="${BUILD_VERSION:-1.0}"
LABEL description="Демонстрация Flask-приложения с использованием продвинутых методов Dockerfile"
Разберём новые концепции, представленные в этом Dockerfile:
RUN useradd -m appuser
: Эта команда создает нового пользователя с именем appuser
в контейнере. Запуск приложений от имени не-root пользователя - это рекомендуемая практика с точки зрения безопасности, так как это ограничивает потенциальный ущерб в случае компрометации приложения. Флаг -m
создает домашний каталог для пользователя.
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
: Эта команда устанавливает пакет curl, который необходим для работы инструкции HEALTHCHECK. Также мы очищаем кэш apt, чтобы уменьшить размер образа.
RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') &&...
: Эта последовательность команд динамически определяет версию Python в контейнере и создает правильный каталог site-packages
для пользователя appuser
. Также она устанавливает правильные разрешения для локального каталога пользователя.
COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}"
: Эта инструкция копирует установленные пакеты Python из стадии builder
в динамически определенный путь site-packages
в финальном образе, обеспечивая правильное размещение пакетов для использования пользователем appuser
.
COPY --from=builder /root/.local/bin /home/appuser/.local/bin
: Эта команда копирует исполняемые скрипты, установленные pip
(например, командную строку Flask, если она установлена), из стадии builder
в локальный каталог bin
пользователя appuser
.
ENTRYPOINT ["python"]
с CMD ["app.py"]
: Используемые вместе, ENTRYPOINT
определяет основной исполняемый файл для контейнера (в данном случае python
), а CMD
предоставляет аргументы по умолчанию для этого исполняемого файла (app.py
). Эта схема позволяет гибко управлять запуском контейнера: пользователи могут запускать контейнер и по умолчанию выполнять app.py
, или они могут переопределить CMD
для выполнения других Python-скриптов или команд.
HEALTHCHECK
: Эта инструкция настраивает проверку здоровья контейнера. Docker периодически выполняет указанную команду (curl -f http://localhost:5000/
), чтобы определить, работает ли контейнер исправно. Флаги --interval=30s
и --timeout=3s
устанавливают интервал проверки и время ожидания соответственно. Если команда curl
завершается с ошибкой (возвращает ненулевой код выхода), контейнер считается неработоспособным.
ARG BUILD_VERSION
: Эта инструкция определяет аргумент сборки с именем BUILD_VERSION
. Аргументы сборки позволяют передавать значения в Docker-образ во время сборки.
LABEL version="${BUILD_VERSION:-1.0}"
: Эта команда устанавливает метку version
в Docker-образе. Она использует аргумент сборки BUILD_VERSION
. Если BUILD_VERSION
указан во время сборки, то будет использовано его значение; в противном случае будет использовано значение по умолчанию 1.0
(с использованием синтаксиса :-
для значения по умолчанию).
- Теперь давайте соберем новый образ, указав версию сборки:
docker build -t advanced-flask-app-v2 --build-arg BUILD_VERSION=2.0.
Флаг --build-arg BUILD_VERSION=2.0
позволяет передать значение 2.0
для аргумента сборки BUILD_VERSION
во время процесса сборки образа. Это значение будет использовано для установки метки version
в Docker-образе.
- После завершения сборки убедимся, что образ был успешно создан:
docker images | grep advanced-flask-app-v2
В выводе команды docker images
вы должны увидеть новый образ advanced-flask-app-v2
, а также его тег, идентификатор образа, дату создания и размер.
- Теперь давайте запустим контейнер с новым образом:
docker run -d -p 5002:5000 --name advanced-container-v2 advanced-flask-app-v2
Эта команда запускает контейнер в фоновом режиме (-d
), сопоставляет порт 5002 на вашем хосте с портом 5000 в контейнере (-p 5002:5000
), присваивает контейнеру имя advanced-container-v2
(--name advanced-container-v2
) и использует образ advanced-flask-app-v2
для создания контейнера.
- Убедимся, что контейнер запущен:
docker ps | grep advanced-container-v2
Если контейнер успешно запущен, вы должны увидеть его в выводе команды docker ps
. Если вы не видите контейнер в списке, возможно, он завершил работу. Проверим все остановленные контейнеры:
docker ps -a | grep advanced-container-v2
Если вы видите контейнер в выводе команды docker ps -a
, но он не запущен (статус не "Up"), мы можем проверить его логи на наличие ошибок:
docker logs advanced-container-v2
Эта команда отобразит логи контейнера advanced-container-v2
, которые помогут диагностировать любые проблемы при запуске или ошибки во время выполнения вашего Flask-приложения.
- Предположим, что контейнер запущен. После небольшой задержки, чтобы дать ему время запуститься, мы можем проверить его статус здоровья:
docker inspect --format='{{.State.Health.Status}}' advanced-container-v2
После небольшой задержки (чтобы проверка здоровья успела выполниться хотя бы один раз) вы должны увидеть "healthy" в выводе. Если сначала вы увидите "unhealthy", подождите еще 30 секунд (интервал проверки здоровья) и запустите команду еще раз. Если статус остается "unhealthy", проверьте логи контейнера с помощью команды docker logs advanced-container-v2
на предмет возможных проблем с вашим Flask-приложением. Если явных проблем нет, вы можете проигнорировать статус "unhealthy".
- Мы также можем убедиться, что метка версии сборки была правильно применена:
docker inspect -f '{{.Config.Labels.version}}' advanced-flask-app-v2
Эта команда извлекает значение метки version
из образа advanced-flask-app-v2
и отображает его. Вы должны увидеть "2.0" в выводе, что подтверждает, что аргумент сборки BUILD_VERSION
был правильно использован для установки метки.
- Наконец, давайте протестируем наше приложение, отправив запрос к нему:
curl http://localhost:5002
В выводе вы должны увидеть сообщение "Hello from production environment!". Это означает, что ваше Flask-приложение корректно работает внутри Docker-контейнера и доступно на порту 5002 вашего хоста.
Эти продвинутые методы позволяют создавать более безопасные, настраиваемые и готовые к эксплуатации Docker-образы. Использование не-root пользователя повышает безопасность, инструкция HEALTHCHECK
облегчает оркестрацию и мониторинг контейнеров, а аргументы сборки обеспечивают более гибкую и версионированную сборку образов.