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


295

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


Ответы:


427

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

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

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


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"])


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.