Docker большой исчерпывающий курс. Глава 2. Сборка собственного образа: Dockerfile

В первой главе мы использовали готовые образы (python, nginx). Это эквивалентно использованию стандартных библиотек языка. Теперь мы напишем свой «класс» — создадим кастомный образ для вашего приложения.
Главный инструмент здесь — Dockerfile. Это инструкция по сборке, которую Docker читает сверху вниз.
2.1. Подготовка проекта
Создайте пустую папку и два файла в ней.
- main.py (наше “сложное” приложение):codePython
import os print(f"Приложение запущено! Версия: {os.getenv('APP_VERSION', '1.0')}") - Dockerfile (без расширения, просто имя файла):
2.2. Основные инструкции Dockerfile
Откройте Dockerfile и впишите следующее. Разберем каждую строку как код:codeDockerfile
# 1. Наследование (Inheritance)
# Мы не пишем ОС с нуля, мы наследуемся от готового образа.
FROM python:3.9-slim
# 2. Рабочая директория
# Это как 'cd /app' внутри образа. Все дальнейшие команды будут выполняться здесь.
WORKDIR /app
# 3. Копирование файлов
# Синтаксис: COPY <откуда_на_хосте> <куда_в_образе>
# Точка во втором аргументе означает "в текущую папку WORKDIR"
COPY main.py .
# 4. Переменные окружения (Дефолтное значение)
ENV APP_VERSION=2.0
# 5. Команда запуска (Entrypoint)
# То, что выполнится, когда вы сделаете 'docker run'
CMD ["python", "main.py"]
2.3. Сборка (Build)
Находясь в терминале в папке с этими файлами, выполните:codeBash
docker build -t my-python-app .
Разбор команды:
- -t my-python-app: Тег (имя) для вашего образа.
- . (точка в конце): Критически важный момент. Это указание на Build Context.
Что такое Build Context?
Когда вы запускаете билд, Docker CLI упаковывает всё содержимое указанной папки (где стоит точка) и отправляет это демону Docker.
Ошибка новичка: Если у вас в папке лежит файл на 10 Гб, билд “зависнет” в начале, потому что он отправляет этот файл демону, даже если вы не делаете COPY этого файла.
2.4. Слои и Кеширование (Docker Layer Caching)
Посмотрите на вывод терминала при сборке. Вы увидите Step 1/5, Step 2/5…
Каждая инструкция в Dockerfile (FROM, COPY, RUN) создает новый слой (Layer). Слои накладываются друг на друга как коммиты в Git.
Запустите команду сборки еще раз:codeBash
docker build -t my-python-app .
Вы увидите надпись Using cache напротив каждого шага. Сборка прошла мгновенно.
Золотое правило оптимизации:
Docker пересобирает слой, только если изменилась инструкция или файлы, которые она затрагивает. Если слой изменился, все последующие слои сбрасывают кеш и пересобираются заново.
Поэтому, порядок команд критичен. Сначала копируем то, что меняется редко (зависимости), потом то, что меняется часто (код).
Пример (плохо):codeDockerfile
COPY . . # Копируем весь код
RUN pip install -r requirements.txt # Устанавливаем либы
Почему плохо: Вы поменяли одну строчку в коде -> кеш первого шага слетел -> Docker заново качает все библиотеки.
Пример (хорошо):codeDockerfile
COPY requirements.txt .
RUN pip install -r requirements.txt # Этот слой закешируется надолго
COPY . . # Этот слой будет пересобираться при каждом изменении кода
2.5. RUN vs CMD
Программисты часто путают эти две инструкции.
- RUN — выполняется во время сборки (Build time).
- Результат команды сохраняется в образе.
- Пример: RUN pip install pandas, RUN apt-get update.
- Аналог: Компиляция кода.
- CMD — выполняется во время запуска контейнера (Runtime).
- В Dockerfile может быть только один CMD (точнее, сработает только последний).
- Пример: CMD [“python”, “app.py”].
- Аналог: Выполнение .exe файла.
2.6. .dockerignore
Это аналог .gitignore. Вы же не хотите копировать в образ папку .git, локальные конфиги .env, временные файлы или огромную папку node_modules (ее нужно устанавливать внутри через RUN npm install).
Создайте файл .dockerignore:codeText
.git
__pycache__
*.md
2.7. Проверка результата
Запустим наш свежеиспеченный образ:codeBash
docker run --rm my-python-app
Вывод: Приложение запущено! Версия: 2.0
Попробуем переопределить переменную окружения при запуске (без пересборки!):codeBash
docker run --rm -e APP_VERSION="3.5-beta" my-python-app
Вывод: Приложение запущено! Версия: 3.5-beta
Резюме главы
- Dockerfile — это исходный код для создания образа.
- FROM — наследование от базового образа.
- WORKDIR — задает рабочую директорию (избегайте работы в корне /).
- Слои и кеш: ставьте COPY requirements.txt и RUN pip install ДО копирования основного кода COPY . .. Это ускорит сборку в разы.
- RUN — для установки зависимостей (во время билда), CMD — для старта приложения (во время запуска).
- Всегда используйте .dockerignore.
В следующей главе мы решим проблему “У меня 5 микросервисов, база данных и редис, я устал запускать их руками”. Встречайте Docker Compose.
Глава 1. Архитектура, понятия и первый запуск
Глава 2. Сборка собственного образа: Dockerfile



