В чём разница между CMD и ENTRYPOINT?
CMD и ENTRYPOINT — это инструкции Dockerfile, определяющие, что будет выполняться при запуске контейнера, но различающиеся поведением при переопределении аргументов.
CMD — команда по умолчанию
CMD задаёт команду, которая легко переопределяется аргументами docker run:
Пример
FROM eclipse-temurin:17-jre-alpine
CMD ["java", "-jar", "app.jar"]
Пример
# Выполнит java -jar app.jar
docker run myapp
# CMD полностью заменяется: выполнит /bin/sh
docker run myapp /bin/sh
ENTRYPOINT — основная команда
ENTRYPOINT задаёт основную команду, а аргументы docker run добавляются к ней:
Пример
FROM eclipse-temurin:17-jre-alpine
ENTRYPOINT ["java", "-jar", "app.jar"]
Пример
# Выполнит java -jar app.jar
docker run myapp
# Аргументы добавятся: java -jar app.jar --spring.profiles.active=prod
docker run myapp --spring.profiles.active=prod
Комбинация ENTRYPOINT + CMD
Идиоматический подход: ENTRYPOINT задаёт исполняемый файл, а CMD — аргументы по умолчанию:
Пример
FROM eclipse-temurin:17-jre-alpine
ENTRYPOINT ["java", "-jar", "app.jar"]
CMD ["--spring.profiles.active=dev"]
Пример
# Выполнит java -jar app.jar --spring.profiles.active=dev
docker run myapp
# CMD заменяется: java -jar app.jar --spring.profiles.active=prod
docker run myapp --spring.profiles.active=prod
Формы записи
| Форма | Синтаксис | PID 1 | Сигналы ОС |
|---|---|---|---|
| Exec-форма (рекомендуется) | ENTRYPOINT ["java", "-jar", "app.jar"] |
Процесс Java | Доходят напрямую |
| Shell-форма | ENTRYPOINT java -jar app.jar |
/bin/sh -c |
Не доходят до Java |
Shell-форма оборачивает команду в /bin/sh -c, из-за чего Java-процесс не получает PID 1 и сигналы ОС (SIGTERM) не доходят до приложения напрямую. Это приводит к проблемам с graceful shutdown.
На собеседовании: ключевое различие: CMD легко переопределяется целиком, а к ENTRYPOINT аргументы добавляются. Идиоматический подход — комбинация ENTRYPOINT + CMD. Обязательно упомяните exec-форму и проблему PID 1 при shell-форме — это показывает production-опыт.