Як передавати аргументи Shell Script через докерний запуск


132

Я новачок у світі докерів. Я повинен викликати скрипт оболонки, який бере аргументи командного рядка через контейнер докера. Наприклад: Мій сценарій оболонки виглядає так:

#!bin/bash
echo $1

Dockerfile виглядає так:

FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh

Я не впевнений, як передавати аргументи під час запуску контейнера

Відповіді:


61

Використовуйте те саме file.sh

#!/bin/bash
echo $1

Створіть зображення за допомогою наявного Dockerfile:

docker build -t test .

Запустіть зображення аргументами abcчи xyzчи іншим.

docker run -ti test /file.sh abc

docker run -ti test /file.sh xyz

27
Я думаю, що ENTRYPOINT - це шлях, якщо ви не хочете, щоб кінцевий користувач знав безпосередньо про file.sh.
greg.kindel

Як ви просто можете запустити такий сценарій docker run -ti test /file.sh abc. Я відчуваю, що сценарій не запускається, тому що він повинен бути docker run -ti test sh /file.sh abc. sh або / bin / sh запустить його правильно.
Вамсідхар Маггулла

1
Для всіх, хто приходить сюди. Трюк / usr / bin / env - це необов'язкове налаштування стилю, а не вимога домогтися цього. Також #! рядок вказує, який інтерпретатор використовувати за замовчуванням buy. Тож він може працювати лише зателефонувавши за сценарієм.
звідки вийшло, що з

164

з цим сценарієм в file.sh

#!/bin/bash
echo Your container args are: "$@"

і це Dockerfile

FROM ubuntu:14.04
COPY ./file.sh /
ENTRYPOINT ["/file.sh"]

ви повинні вміти:

% docker build -t test .
% docker run test hello world
Your container args are: hello world

9
Якщо ви забудете "" навколо "/file.sh", як я це зробив, воно не працюватиме.
кев

6
чомусь це не працює зENTRYPOINT ./file.sh
phil294

6
Не забудьте chmod +x file.shвстановити прапор, що виконується.
topskip

1
@kev, ти знаєш, чому це так? У чому різниця між ["/file.sh"]і /file.shнавіть[/file.sh]
Nitzankin

1
@Nitzankin дивись мою відповідь, чому потрібне правильне форматування json.
BMitch

60

Для Докера правильний спосіб передавати подібну інформацію через змінні середовища.

Тож із тим же Dockerfile змініть сценарій на

#!/bin/bash
echo $FOO

Після побудови використовуйте таку команду docker:

docker run -e FOO="hello world!" test

20
Чому це найвища відповідь? Env vars - це ще один спосіб передачі інформації, але це не те, що задає ОП. І звичайно, немає абсолютно нічого неправомірного в бажанні ОП передавати аргументи до контейнера.
Мінлива хмарність

8
@PartlyCloudy Я думаю, що людям це подобається, оскільки вони хочуть дати "належну" відповідь, незважаючи на те, що явно помиляються. Основним принципом дизайну Докера є пріоритет догми перед здоровим глуздом.
серпня

1
@augurar: Щоб покращити цю відповідь, можливо, ви поясните, чому ви вважаєте, що ця відповідь "очевидно неправильна"?
Еміль Стенстрем

2
Є тонна проблем з XY. Оскільки в ОП заявили, що вони є новими для Докера, цілком розумною є відповідь показати рекомендований спосіб досягнення мети. Таким чином, що це чудова відповідь.
colm.anseo

1
Найпростіший спосіб зробити роботу замість передачі змінних у вигляді аргументів збірки та всього цього безладу. Дуже корисно для передачі секретів як змінні середовища.
Арвінд Шрідхаран

32

Тут взаємодіють кілька речей:

  1. docker run your_image arg1 arg2замінить значення CMDз arg1 arg2. Це повна заміна CMD, не додаючи до нього більше значень. Ось чому ви часто бачите docker run some_image /bin/bashзапускати bash shell в контейнер.

  2. Коли у вас визначено значення ENTRYPOINT і CMD, докер запускає контейнер, об'єднуючи два і запускаючи цю об'єднану команду. Отже, якщо ви визначите, що ваша точка входу є file.sh, тепер ви можете запустити контейнер з додатковими аргументами, які будуть передані як аргументи file.sh.

  3. Вхідні точки та команди в docker мають два синтаксиси, синтаксис рядка, який запустить оболонку, і синтаксис json, який буде виконувати exec. Оболонка корисна для обробки таких речей, як перенаправлення вводу-виводу, з'єднання декількох команд разом (з такими речами, як &&), змінна заміна і т.д. контейнер, це часто є причиною) і об'єднуючи вхідну точку та команду разом. Якщо ви визначите свою вхідну точку як рядок, вона запуститься /bin/sh -c "file.sh", що тільки в порядку. Але якщо у вас також є команда, визначена як рядок, ви побачите щось на кшталт того, /bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"як команда, що запускається всередині вашого контейнера, не дуже гарна. Докладнішу інформацію про взаємодію цих двох варіантів див. У таблиці

  4. Параметр оболонки -cбере лише один аргумент. Все після цього буде передано як $1і $2т. Д. Цьому єдиному аргументу, але не у вбудований скрипт оболонки, якщо ви явно не передали аргументи. Тобто він /bin/sh -c "file.sh $1 $2" "arg1" "arg2"би працював, але /bin/sh -c "file.sh" "arg1" "arg2"не став file.shби тому, щоб його називали без аргументів.

Зважаючи на те, що всі разом, спільний дизайн:

FROM ubuntu:14.04
COPY ./file.sh /
RUN chmod 755 /file.sh
# Note the json syntax on this next line is strict, double quotes, and any syntax
# error will result in a shell being used to run the line.
ENTRYPOINT ["file.sh"]

А ви запускаєте це за допомогою:

docker run your_image arg1 arg2

Про це досить детально:


1
Я експериментував із встановленням вхідної точки, щоб ["bash", "--login", "-c"]отримати джерело / etc / profile на зображенні, але пізніше мені було цікаво, чому жодні аргументи не будуть передані до сценарію оболонки, переданого до запуску докера ... Ваша відповідь очистила це, спасибі !
Apteryx

23

У мене є файл сценарію, який насправді виконує речі. Цей файл сценарію може бути досить складним. Назвемо це "run_container". Цей скрипт бере аргументи з командного рядка:

run_container p1 p2 p3

Простий run_container може бути:

#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"

Що я хочу зробити, це після "докерінгу", я хотів би мати можливість запустити цей контейнер з параметрами в командному рядку docker таким чином:

docker run image_name p1 p2 p3

і щоб сценарій run_container був запущений з параметрами p1 p2 p3.

Це моє рішення:

Докерфайл:

FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]

7
Заміна третього значення на ENTRYPOINT масиву "/run_container \"$@\""засобами аргументів, що містять пробіли, обробляються правильно (наприклад docker run image_name foo 'bar baz' quux).
davidchambers

Після додавання висловлювань перемикання / випадку до мого файлу bash, ENTRYPOINT ["run_container.sh"] для мене більше не працює, але ENTRYPOINT ["sh", "-c", "run_container.sh"] більше не приймає мої параметри. Це рішення (з пропозицією @davidchambers) працювало для мене.
rhamilton

10

Якщо ви хочете запустити його @build time:

CMD /bin/bash /file.sh arg1

якщо ви хочете запустити його @run time:

ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]

Потім в оболонці хоста

docker build -t test .
docker run -i -t test

2
ENTRYPOINTє гарною відповіддю для ОП, який, на мою думку, хотів виконувати, але якщо ви дійсно хочете побудувати змінні часу, ця відповідь просто порушена. Використовуйте ARGта docker build --build-arg docs.docker.com/engine/reference/builder/#arg
greg.kindel

0

Ще один варіант ...

Щоб це спрацювало

docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"

в dockerfile

ENTRYPOINT ["/entrypoint.sh"]

в entrypoint.sh

#!/bin/sh

entrypoint_params=$1
printf "==>[entrypoint.sh] %s\n" "entry_point_param is $entrypoint_params"

PARAM1=$(echo $entrypoint_params | cut -d':' -f1) # output is 1 must be 'bash' it     will be tested    
PARAM2=$(echo $entrypoint_params | cut -d':' -f2) # the real command separated by     &&

printf "==>[entrypoint.sh] %s\n" "PARAM1=$PARAM1"
printf "==>[entrypoint.sh] %s\n" "PARAM2=$PARAM2"

if [ "$PARAM1" = "bash" ];
then
    printf "==>[entrypoint.sh] %s\n" "about to running $PARAM2 command"
    echo $PARAM2 | tr '&&' '\n' | while read cmd; do
        $cmd
    done    
fi

деякі зауваження та обмеження .... команда з ":" потребує змін у cut -d ':', а команди, як docker run -d --rm $ IMG_NAME "bash: echo $ PATH", покажуть значення шляху хосту замість хоста one
wagnermarques
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.