Разница между RUN и CMD в Dockerfile

295

Я не понимаю, когда я должен использовать CMDпротив RUN. Например, для выполнения команд bash / shell (то есть ls -la) я всегда использовал бы CMDили есть ситуация, где я бы использовал RUN? Попытка понять лучшие практики об этих двух похожих Dockerfileдирективах.

TakeSoUp
источник

Ответы:

427

RUN - это шаг построения образа, состояние контейнера после того, как RUNкоманда будет зафиксирована в образе контейнера. Dockerfile может иметь много RUNшагов, которые накладываются друг на друга, чтобы построить образ.

CMD - это команда, которую контейнер выполняет по умолчанию при запуске встроенного образа. Dockerfile будет использовать только окончательный вариант CMD. CMDМожет быть переопределен при запуске контейнера с docker run $image $other_command.

ENTRYPOINT также тесно связан CMDи может изменять способ, которым контейнер запускает изображение.

Matt
источник
15
вы делаете все RUNнеобходимое для настройки вашей среды, и ваш (только) CMD запускает процесс, запущенный в вашем контейнере, например, для nginx, CMD ["nginx", "-g", "daemon off;"]
извлекая
«Dockerfile может иметь только одну CMD» - технически это не так, но фактически все, кроме одного, будут игнорироваться. Смотрите ответ GingerBeer.
Колм Бхандал
«Dockerfile будет использовать только окончательное определение CMD»? на самом деле, окончательное определение CMD будет использоваться при запуске образа как контейнера, верно?
Пол Чунг
1
Да @paulcheung последняя команда в файле docker записывается в образ и является командой, которую контейнер выполняет по умолчанию при запуске встроенного образа.
Мэтт
126

RUN - команда срабатывает при создании образа докера.

CMD - команда срабатывает при запуске созданного образа докера.

Нисал Эду
источник
67

Я нашел это статью очень полезной, чтобы понять разницу между ними:

БЕГАТЬ - инструкция RUN позволяет установить приложение и необходимые для него пакеты. Он выполняет любые команды поверх текущего изображения и создает новый слой, фиксируя результаты. Часто вы найдете несколько инструкций RUN в Dockerfile.

CMD - инструкция CMD позволяет установить команду по умолчанию, которая будет выполняться только при запуске контейнера без указания команды. Если контейнер Docker запускается с командой, команда по умолчанию будет проигнорирована. Если Dockerfile содержит более одной инструкции CMD, все команды CMD, кроме последних
, игнорируются.

фея
источник
13

RUN - установите Python, ваш контейнер теперь сгорел в своем образе python
CMD - python hello.py, запустите ваш любимый скрипт

Рохит Салеча
источник
CMD - Установите Python, мой контейнер теперь не сгорел в своем образе?
Карлос Фонтес
RUN создаст слой изображения python, CMD просто выполнит команду, а не создаст образ
Rohit Salecha
8

Команда RUN: команда RUN в основном выполняет команду по умолчанию, когда мы строим образ. Также будет зафиксировано изменение изображения для следующего шага.

Может быть более 1 команды RUN, чтобы помочь в процессе создания нового образа.

Команда CMD: Команды CMD просто устанавливают команду по умолчанию для нового контейнера. Это не будет выполнено во время сборки.

Если в файле Docker более 1 команды CMD, то все они игнорируются, кроме последней. Поскольку эта команда не будет выполнять ничего, а просто установить команду по умолчанию.

Имбирное пиво
источник
6

Примечание: не путайте RUN с CMD. RUN фактически запускает команду и фиксирует результат; CMD не выполняет ничего во время сборки, но указывает предполагаемую команду для образа.

из ссылки на файл докера

https://docs.docker.com/engine/reference/builder/#cmd

Эльсайед
источник
4

RUN : может быть много, и это используется в процессе сборки , например, установка нескольких библиотек

CMD : Может только 1, что ваш выполнить начальную точку (например ["npm", "start"], ["node", "app.js"])

Xin
источник
2

На RUN и CMD было достаточно ответов . Я просто хочу добавить несколько слов на ENTRYPOINT . Аргументы CMD могут быть перезаписаны аргументами командной строки, тогда как ENTRYPOINT аргументы всегда используются.

Эта статья является хорошим источником информации.

Мило Лу
источник
2

Существующие ответы охватывают большую часть того, что нужно каждому, кто смотрит на этот вопрос. Поэтому я просто расскажу о некоторых нишевых областях для CMD и RUN.

CMD: дубликаты разрешены, но бесполезны

GingerBeer делает важное замечание: вы не получите никаких ошибок, если вставите более одного CMD - но это расточительно. Я хотел бы уточнить на примере:

FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"

Если вы встроите это в образ и запустите контейнер в этом образе, то, как утверждает GingerBeer, будет учитываться только последняя CMD. Таким образом, вывод этого контейнера будет:

Выполнение CMD 2

Я думаю об этом так: «CMD» устанавливает одну глобальную переменную для всего создаваемого образа, поэтому последовательные операторы «CMD» просто перезаписывают любые предыдущие записи в эту глобальную переменную, а в конечном образе, который построен последний, кто пишет, побеждает. Поскольку Dockerfile выполняется в порядке сверху вниз, мы знаем, что самый нижний CMD - это тот, кто получает эту последнюю «запись» (в переносном смысле).

RUN: команды могут не выполняться, если изображения кэшируются

Тонкий момент, на который следует обратить внимание в отношении RUN, - это то, что он рассматривается как чистая функция, даже если есть побочные эффекты, и, следовательно, кешируется. Это означает, что если RUN имел некоторые побочные эффекты, которые не изменяют результирующее изображение, и это изображение уже было кэшировано, RUN больше не будет выполняться, поэтому побочные эффекты не будут возникать при последующих сборках. Например, возьмем этот Dockerfile:

FROM busybox
RUN echo "Just echo while you work"

При первом запуске вы получите такой вывод с разными буквенно-цифровыми идентификаторами:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest

Обратите внимание, что оператор echo был выполнен выше. Второй раз, когда вы запускаете его, он использует кеш, и вы не увидите никакого эха в выходных данных сборки:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Using cache
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest
Колм Бхандал
источник