Использование команды "выполнить" докер для передачи аргументов в cmd в файла Docker

Я новичок в Docker, и мне трудно настроить контейнер docker, как я хочу. У меня есть приложение nodejs может принимать два параметра при запуске. Например, я могу использовать

node server.js 0 dev

или

node server.js 1 prod

для переключения между производственным режимом и режимом dev и определения, следует ли включить кластер. Теперь я хочу создать образ docker с аргументами, чтобы сделать аналогичную вещь, единственное, что я могу сделать, это настроить Dockerfile на есть строка

CMD [ "node", "server.js", "0", "dev"]

и

docker build -t me/app . построить докер.

затем docker run -p 9000:9000 -d me/app для запуска докера.

но если я хочу переключиться в режим prod, мне нужно изменить Dockerfile CMD на

CMD [ "node", "server.js", "1", "prod"] ,

и мне нужно убить старого, слушающего порт 9000 и восстановить изображение. Я хотел бы иметь что-то вроде

docker run -p 9000:9000 environment=dev cluster=0 -d me/app

чтобы создать изображение и запустить nodejs команда с аргументами" environment "и" cluster", поэтому мне больше не нужно изменять Dockerfile и перестраивать docker. Как я могу это сделать?

3 ответов


убедитесь, что ваш Dockerfile объявляет переменную среды С ENV:

ENV environment default_env_value
ENV cluster default_cluster_value

на ENV <key> <value> форма может быть заменено inline.

тут вы можете передать переменную среды с помощью docker run

docker run -p 9000:9000 -e environment=dev -e cluster=0 -d me/app

или установите их через файл compose:

node:
  environment:
    - environment=dev
    - cluster=0

Вашего Файла Docker CMD можно использовать эту переменную среды, но, как указано в вопрос 5509, вам нужно сделать так sh -c форма:

CMD ["sh", "-c", "node server.js ${cluster} ${environment}"]

объяснение заключается в том, что оболочка отвечает за расширение переменных среды, а не Docker. Когда вы используете синтаксис JSON, вы явно запрашиваете, чтобы ваша команда обходила оболочку и выполнялась напрямую.

та же идея с Builder RUN (относится к CMD так же):

в отличие от оболочки форма, форма exec не вызывает командную оболочку.
Это означает, что нормальной обработки оболочки не происходит.

например, RUN [ "echo", "$HOME" ] не будет выполнять подстановку переменных на $HOME. Если вы хотите обработать оболочку, используйте форму оболочки или выполните оболочку напрямую, например:RUN [ "sh", "-c", "echo $HOME" ].

при использовании формы exec и непосредственном выполнении оболочки, как в случае с формой оболочки, именно оболочка выполняет среду переменное расширение, а не докер.


другой вариант-использовать ENTRYPOINT указывает, что node является исполняемым файлом для запуска и CMD предоставить аргументы. Документов пример Exec form ENTRYPOINT example.

используя этот подход, ваш Dockerfile будет выглядеть примерно так:

FROM ...

ENTRYPOINT [ "node",  "server.js" ]
CMD [ "0", "dev" ]

запуск его в dev будет использовать ту же команду

docker run -p 9000:9000 -d me/app

и запустив его в prod, вы передадите параметры в run команда

docker run -p 9000:9000 -d me/app 1 prod

вы можете опустить CMD полностью и всегда проходят в 0 dev или 1 prod в качестве аргументов для команды run. Таким образом, вы случайно не запускаете контейнер prod в dev или контейнер dev в prod.


типичный способ сделать это в контейнерах Docker-передать переменные среды:

docker run -p 9000:9000 -e NODE_ENV=dev -e CLUSTER=0 -d me/app