Что описывается в Dockerfile?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Dockerfile: описание процесса создания Docker образа
Dockerfile — это текстовый файл, который описывает пошаговый процесс создания Docker образа (image). Образ — это своего рода "снимок" приложения со всеми его зависимостями, конфигурацией и кодом. Когда ты запускаешь образ, получается контейнер (container) — изолированное окружение, где работает твоё приложение.
Основная идея
Dockerfile → docker build → Docker Image → docker run → Docker Container
"Инструкция" "Сборка" "Шаблон" "Запуск" "Рабочее ПО"
Базовая структура Dockerfile
# 1. Базовый образ (на основе которого строим наш)
FROM python:3.10-slim
# 2. Автор/мейнтейнер
LABEL maintainer="dev@example.com"
# 3. Переменные окружения для build'а
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
# 4. Рабочая директория в контейнере
WORKDIR /app
# 5. Копирование файлов из хоста в контейнер
COPY requirements.txt .
# 6. Установка зависимостей
RUN pip install --no-cache-dir -r requirements.txt
# 7. Копирование всего приложения
COPY . .
# 8. Экспонирование порта (информационно)
EXPOSE 8000
# 9. Команда запуска (что выполняется при docker run)
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Часть 1: FROM — базовый образ
FROM python:3.10-slim
# или
FROM ubuntu:22.04
# или
FROM node:18
Это образ, с которого начинаем строить. Он уже содержит:
- Операционную систему (Linux)
- Установленные инструменты (для Python: интерпретатор, pip)
- Базовые утилиты
Выбор базового образа важен:
# ✅ python:3.10-slim — 150MB, оптимален для Python приложений
FROM python:3.10-slim
# ❌ python:3.10 — 900MB, содержит много лишнего
# ❌ ubuntu:22.04 — 77MB, но нужно вручную ставить Python
Часть 2: ENV — переменные окружения
ENV PYTHONUNBUFFERED=1
# Python будет выводить логи мгновенно, не буферизировать
ENV PYTHONDONTWRITEBYTECODE=1
# Python не будет создавать .pyc файлы
ENV DATABASE_URL=postgresql://localhost/mydb
# Переменная для приложения (НЕ для production!)
Часть 3: WORKDIR — рабочая директория
WORKDIR /app
# Все последующие команды выполняются из /app
# Эквивалентно:
# RUN mkdir -p /app && cd /app
Часть 4: COPY и ADD — копирование файлов
# Копировать файл requirements.txt в контейнер
COPY requirements.txt .
# COPY <source на хосте> <destination в контейнере>
# Копировать всю папку
COPY . .
# Текущая папка с хоста → текущая папка в контейнере (т.е. /app)
# Исключить файлы (через .dockerignore)
# .dockerignore:
# __pycache__
# *.pyc
# .venv
# .git
Разница COPY vs ADD:
COPY requirements.txt . # ✅ Рекомендуется
ADD https://example.com/file.z . # ✅ Если нужен файл из интернета
ADD archive.tar.gz . # ✅ Если нужно автоматически распаковать
Часть 5: RUN — выполнение команд при build'е
# Установка зависимостей
RUN pip install --no-cache-dir -r requirements.txt
# Несколько команд в одном RUN (экономит слои образа)
RUN apt-get update && \
apt-get install -y postgresql-client && \
rm -rf /var/lib/apt/lists/*
# rm очищает кэш, уменьшает размер образа
# Создание пользователя для безопасности
RUN groupadd -r appuser && useradd -r -g appuser appuser
Часть 6: EXPOSE — экспонирование портов
EXPOSE 8000
# Информирует Docker, что контейнер слушает на порту 8000
# НЕ открывает порт автоматически!
# Для открытия нужно:
# docker run -p 8000:8000 myapp
# или в docker-compose: ports: ["8000:8000"]
Часть 7: CMD vs ENTRYPOINT — команда запуска
# CMD — команда по умолчанию
CMD ["python", "manage.py", "runserver"]
# Это можно переопределить:
# docker run myapp python test.py
# ENTRYPOINT — точка входа, почти не переопределяется
ENTRYPOINT ["python"]
CMD ["manage.py", "runserver"]
# Результат: python manage.py runserver
# docker run myapp = python manage.py runserver
# docker run myapp test.py = python test.py
Практический пример:
# shell form (менее предпочтительно)
CMD python manage.py runserver
# exec form (рекомендуется)
CMD ["python", "manage.py", "runserver"]
# Почему? Exec form передаёт сигналы корректно (SIGTERM, SIGKILL)
Полный пример: Django приложение
# Multi-stage build для уменьшения размера
FROM python:3.10-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# --user устанавливает в ~/.local вместо /usr/local
# Финальный образ
FROM python:3.10-slim
LABEL maintainer="dev@example.com"
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PATH=/home/appuser/.local/bin:$PATH
WORKDIR /app
# Безопасность: использовать непривилегированного пользователя
RUN groupadd -r appuser && useradd -r -g appuser appuser
# Копировать установленные пакеты из builder'а
COPY --from=builder /root/.local /home/appuser/.local
# Копировать код приложения
COPY --chown=appuser:appuser . .
USER appuser
EXPOSE 8000
# Healthcheck (для Kubernetes)
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/health/ || exit 1
CMD ["gunicorn", "myapp.wsgi", "--bind", "0.0.0.0:8000", "--workers=4"]
Процесс сборки образа
# 1. Построить образ
docker build -t myapp:1.0 .
# -t = tag (имя и версия образа)
# . = путь к Dockerfile
# 2. Просмотреть образ
docker images myapp
# 3. Запустить контейнер из образа
docker run -p 8000:8000 myapp:1.0
# 4. Развернуть на production
docker push myregistry.azurecr.io/myapp:1.0
Слои образа (важно для кэширования)
# Каждая инструкция создаёт "слой" (layer)
FROM python:3.10-slim # Слой 1 (от базового образа)
WORKDIR /app # Слой 2
COPY requirements.txt . # Слой 3
RUN pip install -r requirements.txt # Слой 4 (самый большой)
COPY . . # Слой 5
CMD ["python", "main.py"] # Слой 6
Кэширование:
# Если я изменю requirements.txt и пересобираю образ:
# Слои 1, 2 используются из кэша (быстро)
# Слой 3 изменился → пересчитывается
# Слои 4, 5, 6 пересчитываются (долго, потому что pip)
# Оптимизация: поместить stable файлы ранше
COPY requirements.txt . # Меняется редко
RUN pip install -r requirements.txt
COPY . . # Меняется часто
Лучшие практики
# ✅ Используй minimal образы (slim, alpine)
FROM python:3.10-slim # 150MB
# ❌ вместо
FROM python:3.10 # 900MB
# ✅ Минимизируй количество слоёв
RUN apt-get update && apt-get install -y postgresql-client && \
rm -rf /var/lib/apt/lists/*
# ❌ вместо множества RUN команд
# ✅ Используй .dockerignore
# ❌ не копируй лишние файлы
# ✅ Непривилегированный пользователь
USER appuser
# ❌ не запускай как root
# ✅ Multi-stage builds для уменьшения размера
FROM python:3.10 as builder
# ... build
FROM python:3.10-slim
# ... copy from builder
# ✅ HEALTHCHECK для мониторинга
HEALTHCHECK CMD curl http://localhost:8000/health
# ✅ Не коммитьте .env и секреты
# Используй Docker Secrets или environment variables
Dockerfile vs docker-compose
# Dockerfile описывает ОДИ контейнер (образ)
# Для одного приложения
# docker-compose.yml описывает НЕСКОЛЬКО контейнеров
# Для системы сервисов
services:
web:
build: . # Используется Dockerfile для сборки
ports: ["8000:8000"]
environment:
DATABASE_URL: postgres://db:5432/mydb
db:
image: postgres:14
environment:
POSTGRES_DB: mydb
POSTGRES_PASSWORD: secret
Заключение
Dockerfile — это по сути "скрипт инсталляции" для приложения, описывающий:
- Базовую среду (FROM)
- Зависимости (RUN)
- Код приложения (COPY)
- Конфигурацию (ENV, EXPOSE)
- Команду запуска (CMD)
Это делает приложение легко переносимым между машинами (laptop, CI/CD, production) без необходимости устанавливать зависимости вручную. Это фундамент containerized разработки и microservices архитектуры.