Можно ли перезаписать ENTRYPOINT в Docker?

«Можно ли перезаписать ENTRYPOINT в Docker?» — вопрос из категории Docker, который задают на 24% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, инструкцию ENTRYPOINT, определённую в Dockerfile, можно переопределить при запуске контейнера с помощью флага --entrypoint. Это мощная возможность для отладки и выполнения одноразовых команд в среде контейнера.

Синтаксис переопределения:

docker run --entrypoint <новая_команда> <образ> [аргументы...]

Типичные сценарии использования:

  1. Отладка и инспекция: Запуск shell в контейнере, собранном для запуска одного приложения.
    # Образ имеет ENTRYPOINT ["nginx", "-g", "daemon off;"]
    # Мы переопределяем его на /bin/sh для изучения содержимого
    docker run -it --entrypoint /bin/sh my-nginx-image
  2. Выполнение утилит: Запуск встроенных скриптов или команд (например, миграции БД).
    # Предположим, в образе есть скрипт /scripts/migrate.sh
    docker run --entrypoint /scripts/migrate.sh my-app-image

Взаимодействие ENTRYPOINT и CMD: Понимание их совместной работы критично:

  • Exec-форма ENTRYPOINT + CMD: ENTRYPOINT определяет запускаемую программу, а CMD задаёт аргументы по умолчанию для неё.

    # Dockerfile
    FROM alpine
    ENTRYPOINT ["echo"]
    CMD ["Hello from default CMD"]
    • Запуск без переопределения: docker run my-image → вывод: Hello from default CMD
    • Переопределение CMD: docker run my-image Custom Args → вывод: Custom Args (аргументы командной строки заменяют CMD).
    • Переопределение ENTRYPOINT: docker run --entrypoint cat my-image /etc/os-release → выполнится cat /etc/os-release.
  • Shell-форма vs Exec-форма: Всегда предпочтительнее использовать exec-форму (["executable", "param1", "param2"]), а не shell-форму ("executable param1 param2"). Exec-форма гарантирует, что сигналы (например, SIGTERM) будут получены непосредственно процессом, а не оболочкой, что важно для graceful shutdown.

Практический пример для DevOps: Часто в production-образах используется entrypoint-скрипт, который выполняет предварительную настройку (настройку переменных, ожидание готовности зависимостей) перед запуском основного процесса. При необходимости отладки такой скрипт можно обойти.

# Dockerfile
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

Для отладки:

docker run -it --entrypoint /bin/sh nginx-image
# Внутри контейнера можно вручную запустить entrypoint-скрипт или проверить переменные
sh /docker-entrypoint.sh nginx -g 'daemon off;'