Самый простой способ представить это - это то, что ENTRYPOINT
и CMD
определяют списки слов, а последняя команда создается путем объединения этих двух списков.Docker не может узнать, действительно ли первое слово из списка CMD
является исполняемым или нет.
Все три из них при запуске контейнера запускают одну и ту же команду:
FROM busybox
ENTRYPOINT ["/bin/ls"]
CMD ["-lrt", "/"]
FROM busybox
ENTRYPOINT []
CMD ["/bin/ls", "-lrt", "/"]
FROM busybox
ENTRYPOINT ["/bin/ls", "-lrt", "/"]
CMD []
Мой общий опыт состоит в том, что CMD
всегда должна быть правильно сформированной командой.Для этого есть две веские причины: часто docker run --rm -it imagename sh
полезно посмотреть, что получилось в процессе сборки образа;и есть полезная схема установки ENTRYPOINT
для скрипта, который выполняет первоначальную настройку, а затем exec "$@"
для запуска CMD
.(Объедините их, и вы получите отладочную оболочку после первого запуска установки.)
# good
CMD ["/app/myapp", "--foreground"]
# good
ENTRYPOINT ["wait-for-it.sh", "db:5432", "--"]
CMD ["/app/myapp", "--foreground"]
# hard to provide an alternate command or an ENTRYPOINT wrapper
ENTRYPOINT ["/app/myapp"]
CMD ["--foreground"]
В практических целях ENTRYPOINT
должно бытьФорма JSON-массива и не должна использовать оболочку sh -c
.Как отмечается в документации, если ENTRYPOINT
- пустая команда, CMD
игнорируется;если он имеет явную оболочку sh -c
, взаимодействия с дополнительными аргументами не очевидны.
# just prints an empty line
FROM busybox
ENTRYPOINT /bin/echo
CMD ["one", "two", "three", "four"]
# just prints an empty line
FROM busybox
ENTRYPOINT ["/bin/sh", "-c", "/bin/echo"]
CMD ["one", "two", "three", "four"]
На самом деле, ENTRYPOINT
как пустая строка не блокирует CMD
per se ;но результирующие /bin/sh -c 'some command' arg arg
устанавливают $0
, $1
, и т. д. внутри команды способом, который неочевиден.
# prints "three"
FROM busybox
ENTRYPOINT echo $2
CMD ["one", "two", "three", "four"]
# prints "-c"
FROM busybox
ENTRYPOINT echo $1
CMD one two three four