Глиф Учебники

Чем отличаются CMD и ENTRYPOINT

Справочник · Docker · 2 минуты чтения

Обе инструкции задают, что запускается в контейнере. Разница — в том, как их переопределяют:

Пример с CMD

Dockerfile
FROM alpine
CMD ["echo", "Привет, мир"]

Соберите образ в папке с этим Dockerfile (docker build -t hello-cmd .) и запустите:

Терминал
$ docker run --rm hello-cmd
Привет, мир

А docker run --rm hello-cmd date вместо echo запустит date и выведет текущие дату и время: CMD заменился целиком.

Пример с ENTRYPOINT и CMD вместе

Dockerfile
FROM alpine
ENTRYPOINT ["echo", "Привет,"]
CMD ["мир"]

Сборка — docker build -t hello-ep ., запуск:

Терминал
$ docker run --rm hello-ep
Привет, мир
$ docker run --rm hello-ep Docker
Привет, Docker

ENTRYPOINT осталась, а CMD (здесь — аргумент по умолчанию мир) заменился на Docker. Так делают образы- программы: docker run образ --help передаёт --help самой программе.

Заменить и ENTRYPOINT:

Bash
docker run --rm --entrypoint sh hello-ep -c 'echo другая команда'

Таблица

Без ENTRYPOINTENTRYPOINT ["prog"]
Без CMDошибка: запускать нечегоprog
CMD ["arg"]arg (как программа)prog arg
docker run образ x yx yprog x y

Exec-форма и shell-форма

У обеих инструкций две формы записи:

Используйте exec-форму. В shell-форме главным процессом контейнера становится оболочка sh, и сигнал остановки от docker stop до программы может не дойти: Docker подождёт 10 секунд и завершит контейнер принудительно, а программа не успеет сохранить данные. Кроме того, ENTRYPOINT в shell-форме игнорирует и CMD, и аргументы docker run.

В exec-форме кавычки — только двойные. С одинарными (CMD ['python', 'app.py']) Docker не распознает список и запустит строку через оболочку как shell-форму — с непонятной ошибкой.

Что выбрать

Если в Dockerfile несколько CMD или несколько ENTRYPOINT, действует только последняя инструкция каждого вида. И ещё одна тонкость: если в своём Dockerfile задать ENTRYPOINT, то CMD, унаследованный от базового образа, сбрасывается — нужный CMD пишут заново в своём файле.