DOCKER
#docker#containers#cli#devops

Docker: разница между docker run, docker start и docker exec

Практическое объяснение различий между docker run, docker start и docker exec: когда создавать контейнер, когда запускать и как в него входить.

Как использовать

  1. Скопируйте нужный фрагмент кода.
  2. Вставьте в свой проект и при необходимости измените под задачу.
  3. Проверьте зависимости и окружение (версии, переменные).

Три команды часто путают, потому что все они так или иначе «запускают что-то» в Docker. На самом деле они решают разные задачи: run создаёт и запускает новый контейнер, start только запускает уже существующий остановленный контейнер, exec выполняет команду внутри уже запущенного контейнера. Ниже — строго по официальной документации Docker.


docker run — создание и запуск нового контейнера

Описание (из документации): Create and run a new container from an image. Команда запускает команду в новом контейнере, при необходимости подтягивает образ и стартует контейнер.

Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Каждый вызов docker run создаёт новый контейнер из образа. Если контейнер с таким именем уже есть — будет ошибка «Conflict. The container name “/myapp” is already in use», если не использован --rm и не задано уникальное имя.

Типичные сценарии:

  • Первый запуск приложения из образа.
  • Запуск одноразовой задачи (с --rm контейнер удалится после выхода).
  • Запуск с новыми опциями (порты, переменные, тома).
# Создать и запустить контейнер в фоне, с именем и портом
docker run -d --name myapp -p 3000:3000 myimage:1.0

# Создать и запустить с автоматическим удалением после выхода
docker run --rm -it alpine sh

# Создать и запустить с переменными и томом
docker run -d --name db -e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data postgres:16

docker start — повторный запуск остановленного контейнера

Описание (из документации): Start one or more stopped containers. Запускает один или несколько остановленных контейнеров. Контейнер при этом не создаётся заново — используется уже существующий, со всеми прежними настройками и данными.

Usage: docker container start [OPTIONS] CONTAINER [CONTAINER...]
Alias: docker start

Контейнер должен уже существовать (был создан ранее через docker run или API). Команда не принимает имя образа и не создаёт новый контейнер.

Типичные сценарии:

  • Контейнер остановили (docker stop) и нужно снова его запустить.
  • После перезагрузки хоста — запуск ранее созданных контейнеров.
# Запустить контейнер по имени
docker start myapp

# Запустить и сразу прикрепиться к выводу (STDOUT/STDERR)
docker start -a myapp

# Запустить с интерактивным STDIN
docker start -i myapp

# Запустить несколько контейнеров
docker start myapp db redis

Просмотр всех контейнеров (включая остановленные): docker ps -a.


docker exec — выполнение команды внутри запущенного контейнера

Описание (из документации): Run a command in a running container. Выполняет команду в уже запущенном контейнере. Новый контейнер не создаётся, существующий не перезапускается — внутри него просто запускается дополнительный процесс.

Usage: docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]
Alias: docker exec

Контейнер должен быть в состоянии running. Если контейнер остановлен, будет ошибка «Container myapp is not running».

Типичные сценарии:

  • Войти в оболочку контейнера для отладки.
  • Выполнить разовую команду (миграции, бэкап, проверка).
  • Запустить процесс рядом с основным (PID 1).
# Интерактивная оболочка (sh в Alpine, bash в полных образах)
docker exec -it myapp sh

# Выполнить одну команду
docker exec myapp cat /etc/hostname

# Команда с аргументами; для цепочек использовать sh -c
docker exec myapp sh -c "cd /app && npm run migrate"

# Запуск от другого пользователя и в указанной директории
docker exec -u www-data -w /var/www/html myapp pwd

Флаги -i (interactive) и -t (TTY) нужны для интерактивной оболочки; без них ввод с клавиатуры работать не будет.


Сравнение команд

docker run

  • Создаёт новый контейнер из образа.
  • Аргументы: образ, опции, опционально COMMAND.
  • Использовать: первый запуск, одноразовые задачи, новый контейнер с другими опциями.

docker start

  • Не создаёт контейнер; запускает уже существующий остановленный.
  • Аргументы: имя/ID контейнера (одного или нескольких).
  • Использовать: после docker stop, после перезагрузки хоста.

docker exec

  • Не создаёт и не запускает контейнер; выполняет команду в уже работающем.
  • Аргументы: контейнер, команда и аргументы.
  • Использовать: отладка, миграции, любые команды внутри running-контейнера.

Состояние контейнера:

  • docker run — контейнера ещё нет, он создаётся и запускается.
  • docker start — контейнер есть, состояние «exited», переводится в «running».
  • docker exec — контейнер уже «running», внутри него выполняется команда.

Практические примеры (copy-paste)

Полный цикл: создание, остановка, запуск, вход.

# 1. Создать и запустить контейнер
docker run -d --name web -p 8080:80 nginx:alpine

# 2. Проверить, что запущен
docker ps

# 3. Войти в контейнер
docker exec -it web sh

# Внутри контейнера (например, посмотреть конфиг)
# cat /etc/nginx/nginx.conf
# exit

# 4. Остановить контейнер
docker stop web

# 5. Контейнер уже существует, просто запускаем снова
docker start web

# 6. Снова войти
docker exec -it web sh

Ошибка новичка: exec в остановленный контейнер.

docker stop web
docker exec -it web sh
# Error: Container web is not running.

# Правильно: сначала запустить, потом exec
docker start web
docker exec -it web sh

Ошибка новичка: start с образом вместо контейнера.

docker start nginx:alpine
# Error: No such container: nginx:alpine

# docker start принимает только имя или ID контейнера
docker start web

Просмотр контейнеров перед выбором команды.

# Все контейнеры (и запущенные, и остановленные)
docker ps -a

# Только запущенные
docker ps

Типичная ошибка и как её избежать

Ошибка: Пытаются войти в контейнер через docker exec, не проверив, что он запущен. Или вызывают docker start с именем образа вместо имени контейнера.

Как избежать:

  1. Перед docker exec проверять: docker ps — контейнер в списке и в статусе «Up». Если его нет — сначала docker start CONTAINER.
  2. Для docker start использовать только имя или ID контейнера (из вывода docker ps -a), не образ.
  3. Для первого запуска из образа — только docker run; повторный запуск того же контейнера — docker start.

Ссылки на официальную документацию: