Чем отличаются команды docker run и docker exec

Ответ

docker run и docker exec решают разные задачи, связанные с жизненным циклом контейнера.

  • docker run: Создает и запускает новый контейнер из указанного образа. Эта команда инициирует основной процесс контейнера (определенный в CMD или ENTRYPOINT Dockerfile).

  • docker exec: Выполняет дополнительную команду внутри уже запущенного контейнера. Это не влияет на основной процесс контейнера, а запускает новый параллельно.

Практический пример:

  1. Запускаем новый контейнер с веб-сервером Nginx в фоновом режиме:

    # Создаем и запускаем контейнер с именем 'web-server'
    docker run -d --name web-server nginx
  2. Выполняем команду внутри этого контейнера, чтобы посмотреть содержимое директории /usr/share/nginx/html:

    # Запускаем 'ls -l' внутри контейнера 'web-server'
    docker exec web-server ls -l /usr/share/nginx/html
  3. Получаем интерактивный доступ к оболочке контейнера для отладки:

    # Подключаемся к bash-сессии внутри контейнера
    docker exec -it web-server bash

Ключевые отличия:

Критерий docker run docker exec
Цель Создать и запустить новый контейнер Выполнить команду в существующем контейнере
Объект Образ (e.g., nginx) Запущенный контейнер (e.g., web-server)
Жизненный цикл Начинает новый жизненный цикл Работает в рамках существующего
Основной процесс Запускает основной процесс контейнера Не затрагивает основной процесс

Ответ 18+ 🔞

Давай разберём эту дичь, чтобы не путаться, как Герасим с Муму. Представь, что образ — это чертёж табуретки, а контейнер — это уже готовая, хуяк, табуретка.

docker run — это когда ты берёшь чертёж (образ) и собираешь по нему новую табуретку (контейнер), после чего сразу на неё садишься (запускаешь основной процесс). Один раз собрал — один контейнер.

docker exec — это когда табуретка уже стоит, на ней кто-то сидит (основной процесс работает), а ты подбегаешь и, не снимая сидящего, прикручиваешь к ножке, например, фонарик (запускаешь дополнительную команду внутри). Или просто заглядываешь под сиденье.

Пример, чтобы совсем пиздец стало ясно:

  1. Создаём и запускаем новую табуретку-вебсервер (это docker run):

    # Берём чертёж 'nginx', собираем табуретку и называем её 'web-server'. Флаг -d — чтобы она сама в углу стояла.
    docker run -d --name web-server nginx

    Всё, теперь у нас в углу стоит контейнер-табуретка, и на ней автоматически сидит процесс веб-сервера.

  2. Лезем в работающую табуретку (это docker exec). Допустим, хотим посмотреть, что у неё там в кармашке (/usr/share/nginx/html):

    # Суём руку в карман работающей табуретки 'web-server' и шаримся там командой 'ls'
    docker exec web-server ls -l /usr/share/nginx/html

    Веб-сервер при этом продолжает спокойно работать, мы его не трогали.

  3. А теперь хотим влезть в табуретку с головой и поковыряться там от души:

    # Открываем люк (`-it`) в табуретке 'web-server' и запускаем там bash, чтобы похавать
    docker exec -it web-server bash

    Попали внутрь. Сидишь в контейнере как в танке, а веб-сервер снаружи пашет. Красота, ёпта.

Главные отличия, если по-простому:

Критерий docker run docker exec
Что делает Собирает новую табуретку из чертежа и сажает на неё процесс. Лезит в уже собранную и работающую табуретку, чтобы что-то внутри поделать.
С чем работает С образом (чертежом nginx). С контейнером (готовой табуреткой web-server).
Результат Появляется новый контейнер. Внутри старого контейнера выполняется команда.
Основной процесс Его запускает. Его не трогает, работает параллельно.

Короче, run — это чтобы создать, exec — это чтобы в созданное вломиться. Всё, как в жизни.