В чем разница между CMD и ENTRYPOINT в Dockerfile?

в Dockerfiles есть две команды, которые похожи на меня: CMD и ENTRYPOINT. Но я думаю ,что есть (тонкий?) разница между ними-иначе не было бы никакого смысла иметь две команды для одного и того же.

в документации указано для CMD

основная цель CMD-предоставить значения по умолчанию для выполняющегося контейнера.

и ENTRYPOINT:

помогает ENTRYPOINT вы должны настроить контейнер, который можно запустить как исполняемый файл.

Итак, в чем разница между этими двумя командами?

9 ответов


Docker имеет точку входа по умолчанию, которая /bin/sh -c но не имеет команды по умолчанию.

когда вы запускаете docker, как это: docker run -i -t ubuntu bash entrypoint по умолчанию /bin/sh -c изображение ubuntu и команды bash.

команда выполняется через точку входа. т. е. фактическая вещь, которая выполняется, - это /bin/sh -c bash. Это позволило Docker реализовать RUN быстро, полагаясь на синтаксический анализатор оболочки.

позже, люди просили возможность настроить это, так что ENTRYPOINT и .

все, что после ubuntu В приведенном выше примере это команда и передается в точку входа. При использовании CMD инструкция, это точно, как если бы вы делали docker run -i -t ubuntu <cmd>. <cmd> будет параметром точки входа.

вы также получите тот же результат, если вместо этого введите эту команду docker run -i -t ubuntu. Вы все равно запустите оболочку Bash в контейнере из-за ubuntu Файла Docker указан CMD по умолчанию:CMD ["bash"]

как все передается в entrypoint, вы можете иметь очень хорошее поведение от ваших изображений. Пример @Jiri хорош, он показывает, как использовать изображение в качестве "двоичного". При использовании ["/bin/cat"] как entrypoint, а затем делает docker run img /etc/passwd, ты понял,/etc/passwd является командой и передается в точку входа, поэтому выполнение конечного результата просто /bin/cat /etc/passwd.

Другим примером было бы иметь любой cli в качестве точки входа. Для экземпляр, если у вас есть изображение redis, вместо запуска docker run redisimg redis -H something -u toto get key можно просто ENTRYPOINT ["redis", "-H", "something", "-u", "toto"] а затем запустите вот так для того же результата:docker run redisimg get key.


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

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

если вы хотите сделать изображение, посвященное определенной команде, вы будете использовать ENTRYPOINT ["/path/dedicated_command"]

в противном случае, если вы хотите создать образ общего назначения, вы можете оставить ENTRYPOINT неопределенный и использовать CMD ["/path/dedicated_command"] поскольку вы сможете переопределить настройку, предоставив аргументы docker run.

например, если ваш Dockerfile:

FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]

запуск изображения без каких-либо аргументов будет пинговать localhost:

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.088 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.088/0.091/0.096/0.000 ms

теперь запуск изображения с аргументом будет пинговать аргумент:

$ docker run -it test google.com
PING google.com (173.194.45.70): 48 data bytes
56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms
56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms
56 bytes from 173.194.45.70: icmp_seq=4 ttl=55 time=46.379 ms
^C--- google.com ping statistics ---
5 packets transmitted, 3 packets received, 40% packet loss
round-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms

для сравнения, если ваш Dockerfile:

FROM debian:wheezy
CMD ["/bin/ping", "localhost"]

запуск изображения без каких-либо аргументов будет пинговать localhost:

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.076/0.084/0.090/0.000 ms

но запуск изображения с аргументом будет работать аргумент:

docker run -it test bash
root@e8bb7249b843:/#

см. эту статью от Брайана Дехамера для получения более подробной информации: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/


Да, это хороший вопрос. Я еще не совсем понимаю, но:

Я понимаю, что ENTRYPOINT - это двоичный файл, который выполняется. Вы можете переопределить entrypoint по --entrypoint="".

docker run -t -i --entrypoint="/bin/bash" ubuntu

CMD является аргументом по умолчанию для контейнера. Без entrypoint аргумент по умолчанию-это команда, которая выполняется. С entrypoint cmd передается entrypoint в качестве аргумента. Вы можете эмулировать команду с помощью entrypoint.

# no entrypoint
docker run ubuntu /bin/cat /etc/passwd

# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd

Итак, главное преимущество в том, что с помощью entrypoint вы можете передавать аргументы (cmd) в свой контейнер. Для этого вам нужно использовать оба:

# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]

и

docker build -t=cat .

затем вы можете использовать:

docker run cat /etc/passwd
#              ^^^^^^^^^^^
#                   CMD
#          ^^^      
#          image (tag)- using the default ENTRYPOINT

по данным docker docs,

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

  1. Dockerfile должен указать хотя бы один из CMD или ENTRYPOINT команды.
  2. ENTRYPOINT должно быть определено при использовании контейнера в качестве исполняемого файла.
  3. CMD следует использовать в качестве способа определение аргументов по умолчанию для ENTRYPOINT команда или для выполнения специальной команды в контейнер.
  4. CMD будет переопределен при запуске контейнера с альтернативными аргументами.

в таблицах ниже показано какая команда выполняется для различных ENTRYPOINT / CMD комбинации:

-- No ENTRYPOINT

╔════════════════════════════╦═════════════════════════════╗
║ No CMD                     ║ error, not allowed          ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════╝

-- ENTRYPOINT exec_entry p1_entry

╔════════════════════════════╦═══════════════════════════════════════════════════════════╗
║ No CMD                     ║ /bin/sh -c exec_entry p1_entry                            ║
╟────────────────────────────╫───────────────────────────────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ /bin/sh -c exec_entry p1_entry exec_cmd p1_cmd            ║
╟────────────────────────────╫───────────────────────────────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ /bin/sh -c exec_entry p1_entry p1_cmd p2_cmd              ║
╟────────────────────────────╫───────────────────────────────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd ║
╚════════════════════════════╩═══════════════════════════════════════════════════════════╝

-- ENTRYPOINT [“exec_entry”, “p1_entry”]

╔════════════════════════════╦═════════════════════════════════════════════════╗
║ No CMD                     ║ exec_entry p1_entry                             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_entry p1_entry exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ exec_entry p1_entry p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝

в двух словах:

  • CMD задает команду и/или параметры по умолчанию, которые могут быть перезаписаны из командной строки при запуске контейнера docker.
  • команда ENTRYPOINT и параметры не будут перезаписаны из командной строки. Вместо этого все аргументы командной строки будут добавлены после параметров ENTRYPOINT.

Если вам нужно больше деталей или хотел были бы увидеть разницу на примере, то сообщение блога которое всесторонне сравнивает CMD и ENTRYPOINT с большим количеством примеров -http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/


разница между CMD и ENTRYPOINT интуиция:

  • ENTRYPOINT: команда для запуска при запуске контейнера.
  • CMD: команда для запуска при запуске контейнера или аргументы для ENTRYPOINT, если указано.

Да, это смешение.

вы можете переопределить любой из них при запуске docker run.

разница между CMD и ENTRYPOINT by пример:

docker run -it --rm yourcontainer /bin/bash            <-- /bin/bash overrides CMD
                                                       <-- /bin/bash does not override ENTRYPOINT
docker run -it --rm --entrypoint ls yourcontainer      <-- overrides ENTRYPOINT with ls
docker run -it --rm --entrypoint ls yourcontainer  -la  <-- overrides ENTRYPOINT with ls and overrides CMD with -la

подробнее о разнице между CMD и ENTRYPOINT:

до docker run например, /bin / bash переопределяет любую команду CMD, которую мы написали в Dockerfile.

ENTRYPOINT нельзя переопределить во время выполнения с помощью обычных команд, таких как docker run [args]. The args в конце docker run [args] предоставляются в качестве аргументов для ENTRYPOINT. Таким образом, мы можем создать container который похож на обычный двоичный файл, такой как ls.

So CMD может выступать в качестве параметров по умолчанию для ENTRYPOINT, а затем мы можем переопределить cmd args из [args].

ENTRYPOINT можно переопределить с помощью --entrypoint.


принятый ответ сказочный в объяснении истории. Я нахожу, что эта таблица очень хорошо объясняет это из официальный документ "как взаимодействуют CMD и ENTRYPOINT": enter image description here


комментарии к функции EntryPoint в код

/ / ENTRYPOINT / usr / sbin / nginx.

/ / установите точку входа (по умолчанию sh-c) в /usr/sbin/nginx.

// примет CMD в качестве аргументов для /usr/sbin / nginx.

еще одна ссылка из Документы

вы можете использовать форму exec ENTRYPOINT для установки довольно стабильные команды и аргументы по умолчанию и затем используйте CMD для установки дополнительных значений по умолчанию, которые с большей вероятностью будут изменены.

пример:

FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]

построить: sudo docker build-t ent_cmd .

CMD arguments are easy to override.

NO argument (sudo docker -it ent_cmd)                :  ping localhost 
argument    (sudo docker run -it ent_cmd google.com) :  ping google.com

.

To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd

п.с: В присутствии EntryPoint CMD будет содержать аргументы для ввода в EntryPoint. В отсутствие EntryPoint CMD будет командой, которая будет запущена.


CMD:

  • CMD ["executable","param1","param2"]: ["executable","param1","param2"] это первый процесс.
  • CMD command param1 param2: /bin/sh -c CMD command param1 param2 - Это первый процесс. CMD command param1 param2 ответвляется от первого процесса.
  • CMD ["param1","param2"]: эта форма используется для предоставления аргументов по умолчанию для ENTRYPOINT.

ENTRYPOINT (следующий список не учитывает случай, когда CMD и ENTRYPOINT используются вместе):

  • ENTRYPOINT ["executable", "param1", "param2"]: ["executable", "param1", "param2"] первый процесс.
  • ENTRYPOINT command param1 param2: /bin/sh -c command param1 param2 это первый процесс. command param1 param2 ответвляется от первого процесса.

As скрипят сказал, CMD был разработан первым. Затем ENTRYPOINT был разработан для дополнительной настройки. Поскольку они не разработаны вместе, есть некоторые функциональные перекрытия между CMD и ENTRYPOINT, которые часто путают людей.