Основы команды docker run: синтаксис и логика работы
Команда docker run — это фундаментальный инструмент для запуска контейнеров. Каждый DevOps-инженер и системный администратор использует её ежедневно для развертывания сервисов, тестирования и отладки. В этом разделе мы разберем базовый синтаксис и внутреннюю логику работы команды, чтобы вы могли не просто копировать примеры, но и понимать, что происходит на каждом этапе.
Базовый синтаксис и порядок аргументов
Синтаксис команды строго определен: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]. Порядок аргументов критически важен. Сначала указываются опции (флаги), затем имя образа, после которого может быть команда для выполнения внутри контейнера и её аргументы.
Рассмотрим простейший пример: docker run ubuntu echo 'Hello World'. Здесь:
ubuntu— имя образа.echo 'Hello World'— команда и её аргумент, которые будут выполнены внутри нового контейнера.
Docker Engine выполняет следующую последовательность действий:
- Проверяет наличие образа
ubuntuв локальном хранилище. - Если образ отсутствует, автоматически загружает (pull) его из Docker Hub (или другого настроенного реестра).
- Создает новый контейнер — «writable layer» на основе слоев образа.
- Настраивает сетевой интерфейс (по умолчанию bridge) и назначает IP-адрес.
- Запускает указанную команду
echoв этом контейнере. - После выполнения команды контейнер завершает работу (если не указаны флаги для его сохранения).
Это базовый паттерн, на котором строятся все более сложные сценарии.
Что происходит под капотом при запуске `docker run`
Для глубокого понимания и диагностики проблем важно знать внутренние шаги:
- Поиск и подготовка образов: Docker Daemon сначала проверяет локальный кэш. Если образ не найден, происходит его загрузка из реестра. Для версии образа можно использовать теги, например,
ubuntu:22.04. - Создание контейнерного слоя: На основе immutable слоев образа создается верхний, изменяемый (writable) слои. Все изменения файловой системы внутри контейнера записываются здесь.
- Настройка сети: По умолчанию контейнер присоединяется к сети
bridge. Docker создает виртуальный интерфейс, назначает IP из подсети и настраивает маршрутизацию. - Монтирование ресурсов: Если указаны флаги для проброса портов (
-p) или монтирования томов (-v), соответствующие ресурсы хоста связываются с контейнером. - Запуск процесса: Внутри контейнера запускается процесс, указанный в
COMMAND. Если команда не указана, выполняется команда, заданная в образе черезENTRYPOINTилиCMD.
Этот процесс гарантирует изоляцию и воспроизводимость среды, что является ключевым преимуществом Docker.
Ключевые флаги docker run: от новичка до продвинутого пользователя
Флаги команды run позволяют тонко настроить поведение контейнера. Их можно разделить на группы по назначению: управление процессом, сеть, данные, ресурсы и идентификация. Знание ключевых флагов и их комбинаций — основа эффективной работы.
Флаги управления процессом: -d, -it и --restart
Эти флаги определяют, как контейнер запускается и как себя ведет после завершения.
-d(detach): Запускает контейнер в фоновом режиме (как демон). Docker возвращает только Container ID. Используется для сервисов:docker run -d nginx.-it(interactive + tty): Комбинация флагов-i(keep STDIN open) и-t(allocate a pseudo-TTY). Позволяет взаимодействовать с контейнером через терминал, например, для запуска интерактивной сессии Bash:docker run -it ubuntu bash. После выхода контейнер остановится.--rm: Автоматически удаляет контейнер после его остановки. Экономит место и предотвращает накопление «мертвых» контейнеров. Часто используется с-it:docker run -it --rm alpine sh.--restart: Политика автоматического перезапуска. Ключевые значения:no(не перезапускать),on-failure(перезапускать только при ошибке),always(перезапускать всегда, даже после остановки пользователем),unless-stopped(перезапускать всегда, кроме случаев явной остановки пользователемdocker stop). Для production-сервисов рекомендуетсяunless-stopped:docker run -d --restart unless-stopped my-app.
Проброс портов и сетевая изоляция: флаг -p и --network
Чтобы сервис внутри контейнера стал доступен из внешней сети, необходимо пробросить порты.
Синтаксис -p: -p [ХОСТ_ПОРТ]:[КОНТЕЙНЕР_ПОРТ]. Пример: docker run -d -p 8080:80 nginx делает порт 80 контейнера доступным на порте 8080 хоста. Можно указать протокол: -p 80:80/tcp. Для проброса диапазона портов: -p 8000-8010:8000-8010.
Флаг -P: Публикует все порты, экспортированные в образе (через EXPOSE в Dockerfile), на случайные порты хоста. Docker назначает их автоматически.
Создание и использование пользовательских сетей: Для изоляции или особой топологии создаются сети Docker. Пример:
docker network create my-app-network
docker run -d --network my-app-network --name app1 my-image
docker run -d --network my-app-network --name app2 my-imageКонтейнеры app1 и app2 смогут взаимодействовать по именам. Для полной сетевой изоляции используется --network none.
Работа с данными: тома (-v) и монтирование (--mount)
Контейнеры по умолчанию эфемерны — их файловая система очищается после удаления. Для сохранения данных или конфигурации используются тома.
Флаг -v (volume): Синтаксис: -v /путь/на/хосте:/путь/в/контейнере[:опции]. Основные типы:
- Bind mount: Связывает конкретный путь на хосте с контейнером.
docker run -v ./config:/app/config nginx. Данные сохраняются на хосте. - Named volume: Управляемый Docker том с именем. Данны хранятся в области, управляемой Docker, что удобно для переноса и резервного копирования.
docker run -v db_data:/var/lib/postgresql/data postgres.
Флаг --mount: Современный, более явный аналог -v. Синтаксис более читаемый и поддерживает дополнительные опции. Пример: docker run --mount type=bind,source=$(pwd)/html,target=/usr/share/nginx/html nginx.
Важное предупреждение: При использовании bind mounts важно учитывать права доступа (UID/GID). Файлы, созданные контейнером от пользователя root, на хосте будут принадлежать root. Для решения этой проблемы можно использовать флаг --user.
Управление ресурсами: ограничение памяти и CPU
В production-среде необходимо ограничивать ресурсы контейнеров, чтобы предотвратить истощение ресурсов хоста одним сервисом.
- Ограничение памяти: Флаг
-mили--memory. Пример:docker run -m 512m my-appограничивает использование RAM до 512 мегабайт. Можно использовать--memory-swapдля управления swap. - Ограничение CPU: Флаг
--cpusзадает количество (или долю) ядер CPU, доступных контейнеру.docker run --cpus="1.5" my-appограничивает использование до 1.5 ядер. Для привязки к конкретным ядрам используется--cpuset-cpus:docker run --cpuset-cpus="0,2" my-app.
Настройка лимитов — обязательная практика для стабильной работы кластеров и предотвращения ситуаций, когда один контейнер «подвешивает» всю систему.
Практические примеры запуска популярных образов
Теория становится полезной только в применении. Здесь собраны готовые, проверенные команды для самых частых сценариев. Вы можете скопировать их и адаптировать для своих задач.
Запуск Ubuntu для отладки и тестирования
Часто нужен временный, чистый Linux-контейнер для проверки команд, установки пакетов или тестирования скриптов без влияния на основную систему.
docker run -it --rm --name temp-ubuntu ubuntu:22.04 bashОбъяснение флагов:
-it: интерактивный режим с терминалом.--rm: автоматическое удаление контейнера после выхода из bash.--name temp-ubuntu: задает удобное имя для ссылки.ubuntu:22.04: образ с конкретной версией.bash: команда для запуска внутри контейнера.
После запуска вы оказываетесь внутри контейнера. Можно выполнять команды, например, установить curl: apt update && apt install -y curl. После выхода (команда exit) контейнер будет автоматически удален.
Развертывание веб-сервера Nginx с пробросом портов
Стандартный сценарий для быстрого запуска веб-сервера для тестирования или раздачи статического контента.
docker run -d --name my-nginx -p 8080:80 -v $(pwd)/site-content:/usr/share/nginx/html:ro nginxОбъяснение:
-d: запуск в фоновом режиме.--name my-nginx: имя контейнера.-p 8080:80: проброс порта 8080 хоста на порт 80 контейнера. Сервер будет доступен по адресуhttp://localhost:8080.-v $(pwd)/site-content:/usr/share/nginx/html:ro: монтирование каталогаsite-contentиз текущей директории хоста в каталог контейнера в режиме «только чтение» (ro). Это позволяет легко менять содержимое сайта без перезапуска контейнера.
После запуска проверьте работу: curl localhost:8080 или откройте браузер.
Запуск базы данных PostgreSQL с персистентным томом
Для запуска БД в production критически важно сохранять данные после перезапуска или удаления контейнера и безопасно передавать пароли.
docker run -d --name postgres-db -e POSTGRES_PASSWORD=mysecretpassword -v postgres_data:/var/lib/postgresql/data -p 5432:5432 postgres:15Объяснение:
-e POSTGRES_PASSWORD=mysecretpassword: установка переменной окружения, необходимой для инициализации PostgreSQL. Пароль передается напрямую в команде, что небезопасно для production — лучше использовать env-файлы.-v postgres_data:/var/lib/postgresql/data: создание named volumepostgres_dataи его монтирование в директорию данных БД. Данные будут сохраняться в этом томе даже после удаления контейнера.-p 5432:5432: проброс стандартного порта PostgreSQL.
Для реальных проектов используйте файлы переменных окружения (--env-file) и рассмотрите более сложные сетевые конфигурации, например, размещение контейнера в отдельной сети без прямого проброса портов на хост.
Для управления запущенными контейнерами, их остановки, просмотра логов и мониторинга ресурсов обратитесь к нашему полному руководству по командам управления Docker.
Продвинутые сценарии и настройка для production-среды
Базовый запуск контейнера недостаточен для стабильной и безопасной production-среды. Здесь мы рассмотрим практики, которые повышают надежность, безопасность и управляемость ваших сервисов.
Безопасная работа с переменными окружения и env-файлами
Передача секретов (паролей, ключей API) через флаг -e прямо в команде небезопасна: они видны в истории команд и списке процессов. Правильный подход — использование файлов переменных окружения.
Создайте файл .env.prod (и добавьте его в .gitignore!):
DB_PASSWORD=supersecretpassword
API_KEY=xyz123
DEBUG=falseЗапустите контейнер с этим файлом:
docker run --env-file .env.prod -d my-appDocker загрузит все переменные из файла в контейнер. Это стандартный подход в CI/CD и production-развертывании.
Настройка здоровья контейнера (healthcheck) и политик перезапуска
Многие официальные образы (например, для PostgreSQL, Nginx) уже содержат встроенные healthcheck-команды. Но для собственных приложений можно задать кастомную проверку здоровья.
docker run --health-cmd="curl --fail http://localhost:8080/health || exit 1" --health-interval=10s --health-timeout=5s --health-retries=3 -d my-appDocker будет периодически выполнять эту команду внутри контейнера и, в зависимости от статуса, помечать контейнер как healthy или unhealthy. Это критически важно для оркестраторов (Docker Swarm, Kubernetes) и автоматического восстановления.
Политика перезапуска --restart unless-stopped гарантирует, что ваш сервис автоматически запустится после перезагрузки хоста или сбоя демона Docker, если он не был явно остановлен пользователем. Это основа отказоустойчивости.
Управление пользователями и правами внутри контейнера
Запуск контейнеров от пользователя root может создавать проблемы безопасности и конфликты прав при монтировании томов. Файлы, созданные root внутри контейнера, на хосте будут принадлежать root, что затрудняет управление.
Решение — запуск от конкретного UID/GID:
docker run --user $(id -u):$(id -g) -v $(pwd)/data:/app/data my-appЭта команда запустит контейнер от пользователя с тем же UID и GID, что и текущий пользователь хоста. Файлы в mounted volume будут иметь корректные права.
Более правильный подход — создание конкретного пользователя внутри Dockerfile и запуск контейнера от его имени. Это повышает безопасность и соответствует лучшим практикам.
Для построения надежных, безопасных и высокопроизводительных контейнерных сред рекомендуем ознакомиться с нашим практическим гайдом по продвинутому Docker, где детально разбираются механизмы безопасности, сетевые драйверы и тонкая оптимизация.
Типичные ошибки при работе с docker run и как их избежать
Ошибки при запуске контейнеров могут привести к потере данных, недоступности сервисов или безопасности. Знание типичных проблем и их решений поможет вам избежать простоев.
Потеря данных и конфликты при монтировании томов
Ошибка: Использование анонимных томов (без имени) или монтирование пустого каталога хоста в директорию контейнера, где уже есть данные. После удаления контейнера данные исчезают, либо данные контейнера заменяются пустыми файлами хоста.
Решение: Для production-данных всегда используйте named volumes. Они управляются Docker и сохраняются независимо от контейнеров.
docker run -v mysql_data:/var/lib/mysql mysqlДля конфигурационных файлов используйте bind mounts, но убедитесь, что на хосте существует корректная конфигурация. Проверить содержимое тома можно командой docker volume inspect mysql_data.
Проблемы с сетью и занятыми портами
Ошибка: Bind for 0.0.0.0:80 failed: port is already allocated. Попытка пробросить порт, который уже занят другим процессом на хосте.
Диагностика: Найдите процесс, занимающий порт:
sudo ss -tulpn | grep :80
# или
docker ps # для поиска контейнера Docker, использующего портРешения:
- Освободить порт, остановив контейнер или процесс:
docker stop. - Изменить внешний порт:
-p 8080:80. - Использовать другой IP адрес хоста:
-p 192.168.1.10:80:80. - Если порт занят самим Docker демоном из-за предыдущего неудачного запуска, может помочь перезапуск демона (крайняя мера).
Планирование сетевой архитектуры и использование пользовательских сетей Docker помогает избежать конфликтов. Для оркестрации нескольких сервисов рассмотрите использование Docker Swarm, как описано в нашем руководстве по Docker Swarm.
Шпаргалка по команде docker run: сводная таблица флагов и примеров
Эта таблица служит быстрым справочником для опытных специалистов. Здесь собраны ключевые флаги и их типичные применения.
| Категория | Флаг | Описание | Пример использования |
|---|---|---|---|
| Процесс | -d | Запуск в фоновом режиме (detached) | docker run -d nginx |
| Процесс | -it | Интерактивный режим с терминалом | docker run -it ubuntu bash |
| Процесс | --rm | Автоудаление контейнера после остановки | docker run -it --rm alpine sh |
| Процесс | --restart | Политика перезапуска (always, unless-stopped) | docker run -d --restart unless-stopped app |
| Сеть | -p | Проброс порта (host:container) | docker run -p 8080:80 nginx |
| Сеть | --network | Присоединение к пользовательской сети | docker run --network my-net app |
| Данные | -v | Монтирование тома (bind или named volume) | docker run -v ./data:/app/data app |
| Данные | --mount | Современный аналог -v (явный синтаксис) | docker run --mount type=bind,source=./data,target=/app/data app |
| Ресурсы | -m | Ограничение памяти (например, 512m) | docker run -m 512m app |
| Ресурсы | --cpus | Ограничение количества ядер CPU | docker run --cpus="1.5" app |
| Идентификация | --name | Назначение имени контейнера | docker run --name my-container app |
| Безопасность | --user | Запуск от конкретного пользователя (UID:GID) | docker run --user 1000:1000 app |
| Безопасность | --env-file | Загрузка переменных окружения из файла | docker run --env-file .env app |
Популярные комбинации флагов (паттерны):
- Для интерактивного тестирования:
docker run -it --rm --name temp-container ubuntu bash - Для production веб-сервиса:
docker run -d --restart unless-stopped --name web -p 80:80 -v config:/app/config nginx - Для БД с персистентностью:
docker run -d --name db -v db_data:/var/lib/db -e DB_PASSWORD=secret --env-file .env.prod postgres