Существующие ответы охватывают большую часть того, что нужно каждому, кто смотрит на этот вопрос. Поэтому я просто расскажу о некоторых нишевых областях для 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