Пошук уроків, статей та іншого контенту
Порівняєте CMD і ENTRYPOINT, їхні форми запису, комбінування та вплив на запуск контейнера й перевизначення команд.
CMD і ENTRYPOINTCMD і ENTRYPOINT визначають, що саме запускається під час старту контейнера. Вони схожі, але мають різне призначення:
ENTRYPOINT задає основну програму контейнера.
CMD задає команду за замовчуванням або аргументи для ENTRYPOINT.
Команду, задану через CMD, можна замінити під час запуску контейнера.
ENTRYPOINT також можна перевизначити, але для цього потрібен спеціальний параметр --entrypoint.
Наприклад:
FROM alpine:3.20
ENTRYPOINT ["printf", "Запущено з аргументом: %s\n"]
CMD ["за замовчуванням"]Якщо створити й запустити образ:
docker build -t command-demo .
docker run --rm command-demoРезультат:
Запущено з аргументом: за замовчуваннямЯкщо передати власний аргумент:
docker run --rm command-demo productionРезультат:
Запущено з аргументом: productionУ цьому випадку production замінив значення CMD.
Для CMD і ENTRYPOINT доступні дві форми запису:
exec-форма;
shell-форма.
Exec-форма записується як JSON-масив:
CMD ["node", "server.js"]
ENTRYPOINT ["node", "server.js"]Кожен елемент масиву є окремим аргументом команди:
"node" — виконуваний файл;
"server.js" — аргумент.
Exec-форма безпосередньо запускає вказану програму, без проміжної оболонки /bin/sh.
Це зазвичай рекомендований варіант для основного процесу контейнера, оскільки програма отримує сигнали операційної системи без зайвого посередника.
Shell-форма записується як звичайний рядок:
CMD node server.js
ENTRYPOINT node server.jsDocker запускає таку команду через оболонку, зазвичай приблизно як:
/bin/sh -c "node server.js"Shell-форма може бути зручною, коли потрібні можливості оболонки:
підстановка змінних;
оператори && і ||;
перенаправлення введення та виведення;
конвеєри.
Наприклад:
CMD echo "Запуск у середовищі $APP_ENV"Значення $APP_ENV буде підставляти оболонка.
В exec-формі автоматичної підстановки змінних оболонки немає:
CMD ["echo", "Запуск у середовищі $APP_ENV"]У такому випадку програма echo отримає буквальний текст $APP_ENV.
CMD і ENTRYPOINTCMD як команда за замовчуваннямCMD визначає стандартну команду або аргументи, які використовуються, якщо під час запуску контейнера не передати іншу команду.
FROM alpine:3.20
CMD ["echo", "Команда з CMD"]Запуск без додаткових аргументів:
docker run --rm command-demoвиконає:
echo Команда з CMDАле якщо передати власну команду:
docker run --rm command-demo echo "Інша команда"Docker використає її замість CMD.
Результат:
Інша командаENTRYPOINT як основна програмаENTRYPOINT задає програму, яку контейнер призначений запускати.
FROM alpine:3.20
ENTRYPOINT ["echo", "Основна програма"]Запуск без аргументів:
docker run --rm command-demoРезультат:
Основна програмаЯкщо додати аргумент:
docker run --rm command-demo "додатковий текст"Docker передасть цей аргумент до ENTRYPOINT.
Результат:
Основна програма додатковий текстНа відміну від CMD, аргумент командного рядка не замінює ENTRYPOINT. Він додається до нього.
ENTRYPOINT і CMDНайпоширеніший шаблон — exec-форма для обох інструкцій:
FROM alpine:3.20
ENTRYPOINT ["printf", "Режим: %s\n"]
CMD ["development"]Фактична команда за замовчуванням утворюється об’єднанням:
ENTRYPOINT + CMDТобто Docker запускає приблизно:
printf "Режим: %s\n" developmentРезультат:
Режим: developmentПід час запуску з власним аргументом:
docker run --rm command-demo productionCMD замінюється, тому фактично виконується:
printf "Режим: %s\n" productionРезультат:
Режим: productionОтже, для комбінації:
ENTRYPOINT ["executable", "fixed-argument"]
CMD ["default-argument"]Docker використовує:
executable fixed-argument default-argumentА запуск:
docker run image custom-argumentдає:
executable fixed-argument custom-argumentСтворімо образ, у якому ENTRYPOINT фіксує програму, а CMD задає параметри за замовчуванням:
FROM alpine:3.20
# Програма, яку контейнер запускає завжди
ENTRYPOINT ["printf", "Середовище: %s\n"]
# Значення за замовчуванням
CMD ["development"]Команди для перевірки:
docker build -t environment-demo .
docker run --rm environment-demo
docker run --rm environment-demo testing
docker run --rm environment-demo productionРезультат:
Середовище: development
Середовище: testing
Середовище: productionЦей підхід зручний для контейнерів, яким потрібна одна основна програма, але дозволено змінювати її параметри.
CMDКоманда після імені образу замінює CMD:
docker run --rm image custom-commandНаприклад, для такого Dockerfile:
FROM alpine:3.20
CMD ["echo", "Команда за замовчуванням"]ці команди матимуть різні результати:
docker run --rm imageКоманда за замовчуваннямdocker run --rm image echo "Нова команда"Нова командаЯкщо контейнер має ENTRYPOINT в exec-формі, команда після імені образу не замінює ENTRYPOINT, а замінює його аргументи з CMD.
ENTRYPOINTДля заміни ENTRYPOINT використовується параметр --entrypoint:
docker run --rm --entrypoint echo image "Інша точка входу"Наприклад, Dockerfile:
FROM alpine:3.20
ENTRYPOINT ["echo", "Основна точка входу"]
CMD ["значення"]Звичайний запуск:
docker run --rm imageРезультат:
Основна точка входу значенняЗапуск із перевизначеним ENTRYPOINT:
docker run --rm --entrypoint printf image "Нова програма: %s\n"У цьому випадку printf стає новою основною програмою контейнера.
--entrypoint змінює саме ENTRYPOINT. Аргументи, передані після імені образу, використовуються як аргументи нової точки входу.
Для передбачуваного комбінування зазвичай використовують exec-форму:
ENTRYPOINT ["program"]
CMD ["argument"]Shell-форма ENTRYPOINT має іншу поведінку:
ENTRYPOINT program
CMD argumentУ цьому випадку ENTRYPOINT запускається через оболонку. Аргументи з CMD і командного рядка можуть не передаватися основній програмі так, як очікується. Тому shell-форма ENTRYPOINT рідко підходить для контейнерів, яким потрібно гнучко приймати аргументи.
Крім того, shell-процес стає батьківським процесом для програми. Через це сигнали завершення можуть оброблятися не так, як при безпосередньому запуску програми.
Якщо все ж потрібно використати оболонку, можна явно застосувати sh -c в exec-формі:
FROM alpine:3.20
ENTRYPOINT ["sh", "-c", "echo \"Середовище: $APP_ENV\""]Але в такому варіанті потрібно самостійно продумати, як команда отримуватиме аргументи. Для простої програми без команд оболонки краще використовувати exec-форму самої програми.
Для контейнера, який запускає одну програму з параметрами за замовчуванням, використовуйте:
FROM alpine:3.20
ENTRYPOINT ["program"]
CMD ["default-argument"]Наприклад:
FROM alpine:3.20
ENTRYPOINT ["printf", "Порт: %s\n"]
CMD ["8080"]Поведінка:
docker run --rm imageПорт: 8080docker run --rm image 3000Порт: 3000У цьому шаблоні:
ENTRYPOINT визначає незмінну основну програму;
CMD задає параметри за замовчуванням;
аргументи docker run замінюють CMD;
--entrypoint дає змогу повністю замінити основну програму.
Exec-форма повинна бути коректним JSON. JSON використовує подвійні лапки:
CMD ["echo", "Hello"]Неправильно:
CMD ['echo', 'Hello']Такий запис не є коректною JSON-формою.
Неправильно очікувати, що Docker автоматично підставить змінну:
CMD ["echo", "$APP_ENV"]Програма отримає $APP_ENV як звичайний текст. Для підстановки оболонки потрібна shell-форма:
CMD echo "$APP_ENV"Або змінну може обробити сама програма.
ENTRYPOINT звичайною командоюДля такого Dockerfile:
ENTRYPOINT ["echo", "Основна програма"]
CMD ["default"]команда:
docker run --rm image customне замінить ENTRYPOINT. Вона замінить аргументи CMD.
Щоб замінити ENTRYPOINT, потрібно використати:
docker run --rm --entrypoint custom imageТакий запис:
ENTRYPOINT node server.jsзапускає програму через оболонку. Якщо не потрібні оператори оболонки, краще написати:
ENTRYPOINT ["node", "server.js"]Це робить передавання аргументів і завершення процесу більш передбачуваними.
CMDУ Dockerfile можна записати кілька інструкцій CMD, але під час запуску буде використано лише останню:
CMD ["echo", "Перша команда"]
CMD ["echo", "Остання команда"]Фактично використовується:
echo Остання командаЗазвичай у Dockerfile залишають одну інструкцію CMD.
CMD задає команду або аргументи за замовчуванням.
ENTRYPOINT задає основну програму контейнера.
Команда після імені образу замінює CMD.
Параметр --entrypoint замінює ENTRYPOINT.
Exec-форма записується як JSON-масив і зазвичай є кращим вибором для основного процесу.
Shell-форма запускається через оболонку й підтримує її синтаксис.
Найпоширеніше комбінування:
ENTRYPOINT ["program"]
CMD ["default-arguments"]У такому комбінуванні ENTRYPOINT визначає програму, а CMD — її параметри за замовчуванням.