ЯдроКодаподготовка к экзаменам
Учебная платформа

Загружаем материалы

Подготавливаем материалы и навигацию по разделу.

Docker для Python: рабочий Dockerfile веб-приложения и requirements.txt

Автор: · Обновлено

Ниже полный пример Dockerfile для Python с маленьким HTTP-приложением. Сначала обойдёмся стандартной библиотекой: так можно проверить Docker отдельно от загрузки внешних пакетов. Затем добавим вариант с requirements.txt. Все файлы создаются в новой папке python-docker-lab.

Код приложения

Сохраните app.py:

import json
import os
from http.server import BaseHTTPRequestHandler, HTTPServer


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        body = json.dumps({"message": os.getenv("GREETING", "hello-docker")}).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)


HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()

Приложение слушает 0.0.0.0 внутри контейнера. Если привязать его только к 127.0.0.1 контейнера, опубликованный порт не сможет доставить запрос на внешний интерфейс процесса. Этот http.server — учебный пример; для production выбирают подходящий сервер приложения и отдельно решают вопросы таймаутов и конкурентности. Документация Python.

Dockerfile Python-приложения

FROM python:3.13-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY --chown=10001:10001 app.py ./app.py
USER 10001:10001
EXPOSE 8000
CMD ["python", "app.py"]

Создайте .dockerignore:

.git
.venv
__pycache__
*.pyc
.env

В образ копируется конкретный исходник. USER запускает приложение с непривилегированным UID; Python не обязан создавать системную запись пользователя для этого примера. EXPOSE документирует порт, но не публикует его на компьютере. PYTHONUNBUFFERED помогает сразу видеть вывод процесса в логах. JSON-массив CMD не запускает дополнительную shell. Инструкции Dockerfile.

Сборка, запуск, наблюдение

docker build -t dk-python:1 .
docker run -d --name dk-python-web -p 127.0.0.1:18088:8000 -e GREETING=python-ready dk-python:1
curl http://127.0.0.1:18088/
docker logs --tail 20 dk-python-web
docker exec dk-python-web id
docker stop dk-python-web
docker rm dk-python-web

В PowerShell используйте curl.exe. Ответ должен содержать {"message": "python-ready"}, а id — UID 10001. Перед первым HTTP-запросом дайте процессу запуститься; если запрос слишком ранний, повторите его. Значение GREETING передаётся при запуске; для его изменения сборка нового образа не нужна.

Когда появились внешние зависимости

Создайте requirements.txt с одной строкой packaging==25.0. Версия закреплена для учебного эксперимента, а не объявлена самой новой. Замените Dockerfile на вариант:

FROM python:3.13-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY --chown=10001:10001 app.py ./app.py
USER 10001:10001
EXPOSE 8000
CMD ["python", "app.py"]

Соберите docker build -t dk-python:deps ., затем выполните docker run --rm dk-python:deps python -c "import packaging; print(packaging.__version__)". Ожидается 25.0. Установка зависимостей стоит до копирования исходника: изменение app.py не требует повторять pip install, если предыдущие входы неизменны. Для реального проекта фиксируют весь граф зависимостей и при необходимости хеши, а не только верхнеуровневые пакеты. Python-образ в Docker.

Ошибка и упражнение

Если сервер не открывается, проверьте docker ps -a, logs, адрес bind в Python и обе стороны -p. ModuleNotFoundError требует проверить пакет внутри образа, а не наличие библиотеки в вашей .venv. Ошибка PermissionError означает, что UID процесса не может писать в выбранный путь; не исправляйте её запуском всего приложения от root без разбора.

Добавьте поле path в JSON-ответ, соберите тег :2, запустите его на другом свободном порту и проверьте /lesson. Затем объясните, почему изменения app.py требуют сборки, а изменение GREETING — только нового контейнера с другой конфигурацией. Это две разные причины пересоздания среды.

Источники