Как создать образ в Docker
В этой статье мы подробно рассмотрим весь процесс создания образа: от установки Docker и написания Dockerfile до версионирования и загрузки образов в реестр. Материал подойдет всем — от новичков, которые впервые слышат слово контейнеризация, до практикующих разработчиков, желающих систематизировать свои знания.
Docker — это мощная технология, которая позволяет создавать, развертывать и управлять контейнерами. Контейнеры представляют собой изолированные среды, в которых можно запускать приложения со всеми их зависимостями, что делает процесс разработки и развертывания более предсказуемым и удобным. Docker помогает разработчикам упростить процесс сборки и развертывания приложений, устраняя проблемы с совместимостью между различными системами. Благодаря Docker, вы можете легко переносить приложения между серверами, виртуальными машинами и облачными платформами, что особенно полезно в DevOps-практиках.
Эта статья будет полезна, когда потребуется создать собственный образ — будь то упаковка Python-приложения, веб-сервера Nginx или любого другого сервиса для запуска на сервере. Сейчас рассмотрим, как установить Docker на сервер, а затем — как собрать и запустить ваш первый образ в production-среде.
Установка Docker
Для установки Docker на сервер или локальную машину необходимо выполнить несколько шагов. Если вы используете дистрибутив Ubuntu или Debian, начните с обновления пакетов системы командой:
sudo apt update
Затем установите необходимые зависимости, такие как apt-transport-https и ca-certificates:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
После этого добавьте официальный репозиторий Docker в вашу систему и установите пакет docker-ce (Community Edition). Для проверки подлинности пакетов добавьте GPG-ключ Docker:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Добавьте репозиторий Docker:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
Обновите список пакетов и установите Docker СE:
sudo apt update && sudo apt install docker-ce
Для завершения настройки добавьте вашего пользователя в группу docker, чтобы иметь возможность управлять контейнерами без использования sudo.
sudo usermod -aG docker $USER
После установки проверьте, что Docker работает, выполнив команду docker —version. Теперь вы готовы к созданию и развертыванию контейнеров!
Создание образа
Docker позволяет создать образ на основе инструкций, описанных в Dockerfile. Этот файл содержит все необходимые шаги для сборки окружения: установку зависимостей, копирование файлов проекта, настройку переменных среды и запуск приложения.
Пример Dockerfile для Python-приложения с Nginx:
# Базовый образ
FROM python:3.9-slim
# Установка зависимостей
RUN apt-get update && apt-get install -y nginx
# Копирование файлов проекта
WORKDIR /app
COPY . .
# Установка Python-зависимостей
RUN pip install -r requirements.txt
# Настройка переменных окружения
ENV FLASK_APP=app.py
# Открытие порта
EXPOSE 80
# Команда для запуска приложения
CMD ["gunicorn", "--bind", "0.0.0.0:80", "app:app"]
Рассмотрим подробнее ключевые команды, которые можно использовать в Dockerfile.
- FROM — указывает исходный образ, на котором будет строиться контейнер. Docker загружает его из реестра (Docker Hub).
- RUN — выполнение команд в процессе сборки (например, установка пакетов).
- WORKDIR — задает рабочую директорию внутри контейнера, где будут выполняться остальные команды.
- COPY — копирование файлов из директории проекта в контейнер.
- ENV — устанавливает переменные среды, которые будут доступны внутри контейнера.
- EXPOSE — указывает, какие порты будет использовать контейнер, но не пробрасывает их автоматически.
- CMD — команда для запуска приложения, выполняется при старте контейнера.
Для сборки образа перейдите в каталог с Dockerfile и выполните:
docker build -t my-python-app .
В данном примере флаг -t задает имя образа (my-python-app). Символ точки в конце — это путь к Dockerfile (текущая директория).
Запуск контейнера выполняется командой:
docker run -d -p 80:80 --name my-container my-python-app
Для запуска в фоновом режиме добавлен флаг -d, затем осуществляется проброс портов (хост:контейнер) с флагом -p 80:80 и указывается имя контейнера с помощью —name.
Для проверки, что контейнеры запущены, выполните команду:
docker ps
Если необходимо остановить и удалить контейнеры, выполните команды stop и rm:
docker stop my-container && docker rm my-container
Следуя данным инструкциям, можно создать свой образ через Dockerfile, осуществить сборку и развернуть в работающий контейнер. В дальнейшем можно оптимизировать образ (уменьшить размер) или использовать Docker Compose для управления несколькими сервисами.
Редактирование существующего образа
Есть три основных способа изменить готовый образ Docker. Рассмотрим каждый с примерами. Рекомендуемый способ — сделать это через Dockerfile. Если есть доступ к Dockerfile, то можно внести в него изменения. Затем — пересобрать образ с новым тегом. Например:
docker build -t my-image:v2 . # Версия 2
Данный способ позволяет прозрачно изменять образы на постоянной основе. При этом все изменения задокументированы в Dockerfile.
Если Dockerfile недоступен, то можно использовать временный контейнер. Для этого нужно поэтапно выполнить инструкции:
# Запуск контейнера из исходного образа в интерактивном режиме
docker run -it --name temp-container ubuntu:22.04 /bin/bash
# Обновление пакетов или изменение файлов
apt update && apt install -y curl
# Сохраненеи изменений в новый образ
docker commit temp-container my-edited-image
# Удаление временного контейнера
docker rm temp-container
Данный способ выполняется достаточно быстро, чтобы протестировать обновления. Но будет отсутствовать история изменений, как при версионировании Dockerfile.
В экстренных случаях можно использовать docker commit. Данный способ подходит для срочных правок без остановки контейнера.
docker commit my-edited-image
Важно отметить, что ручные правки через docker commit могут увеличить размер, потому что останутся временные файлы. Оптимальное решение — пересборка через Dockerfile. Для проверки изменений можно сравнить слои образа:
docker history my-image
Подводя итог, можно сказать, что для долгосрочных правок нужно вносить изменения через Dockerfile. Для тестирования и временных изменений подойдет временный контейнер. Для экстренных исправлений — использование docker commit.
Создание бэкапа и восстановление
Резервное копирование (бэкап) образов Docker позволяет переносить их между системами или сохранять на случай сбоев.
Экспорт образа
Команда docker save сохраняет образ со всеми слоями в один архив (файл .tar):
docker save -o my-backup.tar my-image:latest
В данном примере имя файла для сохранения определяется после флага -o, затем указывается имя образа и его тег. Пример для образа nginx:alpine:
docker save -o nginx-backup.tar nginx:alpine
Проверка содержимого архива:
tar -tf nginx-backup.tar # Просмотр списка файлов в архиве
Импорт образа
Чтобы восстановить образ на другой машине или после удаления из файла .tar, используйте команду:
docker load -i my-backup.tar
Проверка загруженного образа:
docker images # В списке должен появиться ваш образ
Экспорт контейнера
Если нужно сохранить контейнер (включая его файловую систему), используйте docker export:
docker export -o my-container.tar my-container
Важно отметить, что экспортируется только файловая система — без метаданных, слоев и истории. А для дальнейшего восстановления потребуется команда docker import.
Импорт контейнера
Для импорта контейнера из файла .tar нужно воспользоваться командой docker import, которая создает новый образ из файловой системы контейнера:
docker import my-container.tar my-new-image:latest
В отличие от docker load команда import создает новый образ из файлов контейнера (без истории слоев). Команда load — восстанавливает оригинальный образ со всеми слоями.
Полезные команды при выполнении бэкапов
В процессе выполнения подобных операций (экспорт/импорт) могут быть использованы и другие команды для промежуточных работ или контроля состояния системы. Например, можно вывести список образов:
docker images
Удалить образ можно с помощью docker rmi:
docker rmi my-image:latest
Проверить наличие образа после импорта — через docker history:
docker history my-new-image # Покажет слои (если были сохранены)
Для эффективного резервного копирования в Docker важно правильно выбрать инструмент. Используйте docker save для полного сохранения образа со всеми слоями и метаданными (идеально для создания резервной копии), а docker export — если нужно сохранить только текущее состояние файловой системы контейнера, но без истории изменений.
Для восстановления при переносе образа применяйте docker load (возвращает оригинальный образ) или docker import (создает новый образ из контейнера). Ключевое различие при создании бэкапов: save/load работают с образами, а export/import — с контейнерами.
Оптимизация размера образа
Слишком большие Docker-образы замедляют развертывание и расходуют дисковое пространство. Есть несколько простых шагов, на которые стоит обратить внимание при формировании Dockerfile.
1. Используйте легковесный базовый образ. Например, замените python:3.9 на python:3.9-slim. Это позволит сэкономить до 50% размера (образ slim ~120 МБ vs стандартный ~900 МБ).
2. Удаляйте кэш пакетов после установки. Добавьте —no-cache-dir для pip и чистите apt.
RUN pip install --no-cache-dir -r requirements.txt && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
3. Копируйте только нужные файлы. Исключите виртуальные окружения, кэши логи.
# В место COPY . /app
COPY requirements.txt /app/
COPY src/ /app/src/ # Только нужные директории
4. Объединяйте команды RUN. Каждая инструкция RUN создает новый слой — объединяйте их через &&:
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc python3-dev && \
pip install --no-cache-dir -r requirements.txt && \
apt-get remove -y gcc python3-dev && \
apt-get autoremove -y
5. Используйте .dockerignore файл, чтобы не сохранять в образ созданные для разработки файлы и директории. Пример:
__pycache__/
*.pyc
.env
.git/
venv/
Также существуют более профессиональные методы оптимизации образа Docker. Например, многоэтапная сборка (Multi-stage). Особенность данного подхода в том, чтобы отделить этап сборки от финального образа. В результате итоговый образ содержит только нужные файлы:
# Этап сборки
FROM python:3.9 as builder
COPY requirements.txt .
RUN pip install --user -r requirements.txt
# Финальный образ
FROM python:3.9-slim
COPY --from=builder /root/.local /usr/local
COPY src/ /app
Оптимизация Docker-образов — это баланс между минимализмом и работоспособностью. Применив данные рекомендации, можно добиться сокращения размера до 50% образа без потери функциональности.
Версионирование
Версионирование Docker-образов — ключевая практика для контроля изменений, отката к предыдущим состояниям и безопасного развертывания. Правильная система тегов помогает командам избежать хаоса в production-среде и упрощает совместную работу.
Версионирование начинается с правильной системы тегов при сборке образа. Самый надежный подход — использовать семантическое версионирование (SemVer) в формате MAJOR.MINOR.PATCH. Например, для сборки образа версии 1.0.0 выполните:
docker build -t my-app:1.0.0 .
Тег latest лучше избегать в production, так как он не дает понимания, какая именно версия развернута. Вместо этого используйте четкие версии и дополнительные алиасы для удобства, например:
docker tag my-app:1.0.0 my-app:stable
Для хранения версий загружайте образы в Docker Hub или приватный реестр (например, GitLab Registry):
docker push my-app:1.0.0
Автоматизировать процесс помогут CI/CD-системы. В GitLab CI можно привязать версию к тегу коммита:
build:
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
Чтобы проверить доступные версии образа, используйте:
docker images my-app
Для сложных проектов добавляйте в теги хеш коммита (my-app:1.0.0-gitabc123). Это даст полную трассировку изменений.
Версионирование Docker-образов — это не просто «хороший тон», а необходимость для стабильной работы приложений. Используйте семантическое версионирование (semver), избегайте тега latest в production и автоматизируйте процесс через CI/CD. Так вы всегда сможете откатить изменения и точно знать, какая версия образа работает в вашей среде.
Загрузка образа на Docker Hub
Docker Hub — это популярный облачный реестр для хранения и распространения Docker-образов. Загрузка образа в реестр позволяет легко делиться им с командой или развертывать в облачных сервисах. Давайте разберемся, как правильно опубликовать образ, чтобы избежать распространенных ошибок.
Перед загрузкой убедитесь, что образ собран и имеет корректный тег. Он должен включать имя вашего репозитория на Docker Hub в формате username/repository:tag. Например, если ваш логин на Docker Hub — devuser, а проект называется my-python-app, выполните:
docker tag my-app:1.0.0 devuser/my-python-app:1.0.0
Теперь необходимо авторизоваться в Docker Hub через командную строку. Введите:
docker login
После ввода логина и пароля можно загружать образ:
docker push devuser/my-python-app:1.0.0
Если вы хотите загрузить несколько тегов одного образа, придется повторить команду push для каждого тега. Для проверки успешной загрузки откройте свой профиль на Docker Hub в браузере. Там должен появиться новый репозиторий с загруженным образом.
Загрузка образов на Docker Hub — это простой, но важный этап в работе с Docker. Всего несколько команд (docker tag, docker login и docker push) — и ваш образ готов к использованию в любой системе. Главное не забывать указывать правильные теги и следить за тем, чтобы в реестр не попадали временные или тестовые сборки.
Удаление образа
В процессе работы с Docker дисковое пространство постепенно заполняется неиспользуемыми образами, что может стать проблемой на серверах с ограниченными ресурсами. Правильное удаление образов помогает поддерживать порядок в системе и освобождать место для новых сборок.
Для начала стоит просмотреть список всех образов в системе, выполнив команду docker images. Это поможет идентифицировать, какие именно образы занимают место и какие из них можно удалить. Чтобы удалить конкретный образ, используйте команду docker rmi с указанием ID образа или его тега. Например:
docker rmi my-app:1.0.0
Если образ используется в каком-либо контейнере (даже остановленном), Docker не позволит его удалить, пока вы не удалите зависимые контейнеры командой docker rm. Для принудительного удаления образа без проверки зависимостей можно добавить флаг -f:
docker rmi -f my-app:1.0.0
Для массовой очистки всех неиспользуемых образов (dangling) воспользуйтесь командой:
docker image prune
А чтобы удалить вообще все образы, которые не имеют запущенных контейнеров, добавьте флаг -a:
docker image prune -a
Регулярное удаление неиспользуемых образов — важная часть поддержания порядка в Docker-окружении. Используя docker rmi для точечного удаления и docker image prune для массовой очистки, вы сможете эффективно управлять дисковым пространством. Помните: перед удалением стоит убедиться, что образ действительно больше не нужен — восстановить его после удаления можно будет только через повторную сборку или загрузку из реестра.