← Назад к вопросам

В чем разница между docker run и docker exec?

1.0 Junior🔥 241 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

В чем разница между docker run и docker exec?

Это два кардинально разных способа запуска команд в Docker. Разберём их с примерами.

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

docker run создаёт новый контейнер из образа и запускает команду внутри него.

# Создаёт новый контейнер с именем my-app, запускает Python приложение
docker run --name my-app python:3.11 python app.py

# Создаёт контейнер с маппингом портов и переменными окружения
docker run -d \
  --name web-server \
  -p 8000:5000 \
  -e DEBUG=true \
  my-python-app:latest

# Каждый запуск docker run создаёт новый контейнер
docker run python:3.11 echo "Hello"      # Создан контейнер 1
docker run python:3.11 echo "Hello"      # Создан контейнер 2 (другой!)
docker ps -a | grep python               # Видны оба контейнера

Жизненный цикл:

  1. Образ скачивается (если нужно)
  2. Создаётся новый контейнер
  3. Запускается команда
  4. Контейнер может остановиться или работать дальше

2. docker exec — выполнение команды в существующем контейнере

docker exec выполняет команду внутри уже работающего контейнера. Контейнер уже существует и работает.

# Сначала запускаем контейнер
docker run -d --name my-app python:3.11 python app.py

# Теперь можем выполнить команду внутри него
docker exec my-app ls /app              # Список файлов
docker exec my-app python -c "import sys; print(sys.version)"

# Интерактивное взаимодействие с оболочкой
docker exec -it my-app /bin/bash        # Входим в оболочку контейнера
# Теперь ты внутри контейнера, можешь писать команды интерактивно
root@container:/app# ls
root@container:/app# python debug.py
root@container:/app# exit

3. Ключевые отличия в таблице

Аспектdocker rundocker exec
Что делаетСоздаёт новый контейнерВыполняет в существующем
ТребуетТолько образРаботающий контейнер
Состояние контейнераНе важноДолжен быть запущен
ИзоляцияПолная (новая ОС)В том же контейнере
ДанныеНовые файлыВидит файлы контейнера
Переменные окруженияЗадаются флагами -eУже заданы в контейнере

4. Практические примеры

Сценарий 1: Локальная разработка

# Запускаем контейнер базы данных один раз
docker run -d \
  --name postgres-db \
  -e POSTGRES_PASSWORD=secret \
  -p 5432:5432 \
  postgres:15

# Выполняем миграции
docker exec postgres-db psql -U postgres -d myapp -f /migrations/001_init.sql

# Добавляем тестовые данные
docker exec postgres-db psql -U postgres -c "INSERT INTO users (name) VALUES (Alice)"

# Проверяем результат
docker exec postgres-db psql -U postgres -c "SELECT * FROM users"

Сценарий 2: Отладка production приложения

# Приложение уже работает (docker run выполнена ранее)
docker ps
# CONTAINER ID  IMAGE             NAMES
# abc123        myapp:1.0.0       production-app

# Нужно проверить логи и отладить
docker exec production-app tail -100 /var/log/app.log
docker exec production-app env | grep DEBUG
docker exec -it production-app /bin/bash  # Интерактивная оболочка

# А если бы мы использовали docker run, создался бы второй контейнер!
docker run -it myapp:1.0.0 /bin/bash     # НОВЫЙ контейнер, не тот что работает

Сценарий 3: Запуск Python скрипта

# Вариант 1: docker run — создаёт контейнер, выполняет скрипт, контейнер может остановиться
docker run --rm -v $(pwd):/app python:3.11 python /app/script.py
# --rm автоматически удаляет контейнер после выполнения

# Вариант 2: docker exec — контейнер должен быть запущен
docker run -d --name persistent-python python:3.11 tail -f /dev/null  # Держим контейнер живым
docker exec persistent-python python /app/script.py
docker exec persistent-python python /app/another_script.py  # Второй скрипт в том же контейнере

5. docker run с флагом -d (detached mode)

Часто люди путаются, потому что docker run -d запускает контейнер в фоне:

# Запускаем в фоне
docker run -d --name my-service python:3.11 python app.py

# Контейнер работает, но мы вернулись в терминал
docker ps  # Видим мой контейнер

# Теперь можем использовать docker exec
docker exec my-service python test.py
docker exec -it my-service /bin/bash

Это часто используется вместо docker exec: сначала docker run -d, потом docker exec.

6. Когда что использовать?

Используй docker run, если:

  • Нужно создать новый контейнер
  • Запускаешь одноразовую задачу (скрипт, миграция)
  • Нужна изоляция от других процессов
  • Создаёшь новый сервис
# Миграция БД перед запуском приложения
docker run --rm \
  --network app-network \
  my-app:latest \
  python migrate.py

Используй docker exec, если:

  • Контейнер уже работает
  • Нужно отладить или проверить состояние
  • Выполняешь команду в контексте работающего приложения
  • Нужна интерактивная оболочка
# Проверить логи работающего контейнера
docker exec production-app tail -f /var/log/app.log

# Интерактивная отладка
docker exec -it production-app /bin/bash

7. Практический пример: полный цикл

# 1. Создаём контейнер с приложением (docker run)
docker run -d \
  --name myapp \
  -p 8000:8000 \
  -e DATABASE_URL=postgres://db:5432/myapp \
  myapp:1.0.0

# 2. Проверяем, работает ли (docker exec)
docker exec myapp curl localhost:8000/health

# 3. Смотрим логи (docker exec)
docker exec myapp tail -100 /var/log/app.log

# 4. Отлаживаем через оболочку (docker exec)
docker exec -it myapp /bin/bash
# >>> python manage.py shell
# >>> from models import User
# >>> User.objects.all()

# 5. Когда всё готово, контейнер работает дальше
# docker run создал, docker exec помогает управлять

Итог

  • docker run = создание и запуск нового контейнера
  • docker exec = выполнение команды в уже работающем контейнере

В production обычно сначала делают docker run -d для запуска сервиса, а потом docker exec для отладки и управления. Это как создать процесс (docker run) и затем взаимодействовать с ним (docker exec).