Запуск сценария внутри контейнера докеров с использованием сценария оболочки

88

Я пытаюсь создать сценарий оболочки для настройки контейнера докеров. Мой файл сценария выглядит так:

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

Запуск этого файла сценария запустит контейнер во вновь вызванном bash.

Теперь мне нужно запустить файл сценария (test.sh), который уже находится внутри контейнера из указанного выше сценария оболочки. (Например: cd /path/to/test.sh && ./test.sh) Как это сделать?

прыгать
источник
1
Почему бы не использовать WORKDIRи CMD?
Dharmit
1
Вы, вероятно, не захотите использовать здесь --privileged. См .: stackoverflow.com/questions/36425230/…
CMP

Ответы:

123

Вы можете запустить команду в работающем контейнере, используя docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:

docker exec mycontainer /path/to/test.sh

И для запуска из сеанса bash:

docker exec -it mycontainer /bin/bash

Оттуда вы можете запустить свой скрипт.

Хавьер Кортехосо
источник
6
что, если мне нужно сначала войти в / bin / bash, а затем запустить команду внутри этого bash?
zappy
49
Вы также можете запустить локальный скрипт напрямую с хоста. docker exec -i mycontainer bash < mylocal.sh Это читает локальный скрипт хоста и запускает его внутри контейнера. Вы можете сделать это с другими вещами (например, с файлами .tgz, передаваемыми по конвейеру в tar) - просто используйте '-i' для передачи в стандартный ввод процесса контейнера.
Марвин
@Marvin какой эквивалент в PowerShell? символ "<" не распознается.
Nicekiwi
1
Я не гуру PowerShell (к счастью), но я бродил по SO и нашел stackoverflow.com/a/11788475/500902 . Так что, может быть Get-Content mylocal.sh | docker exec -i mycontainer bash. Я не знаю, работает ли это.
Марвин
99

Предполагая, что ваш док-контейнер запущен и работает, вы можете запускать команды как:

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"
Циклоп
источник
2
Мне нравится этот ответ; вам не нужно входить в контейнер докеров, чтобы выполнить команду или набор команд. Спасибо!
Hatem Jaber
Вы знаете, как сделать еще один шаг и передать всю команду ( /bin/sh -c "cmd1; cmd2; ...; cmdn") в качестве значения переменной оболочки? Я спрашиваю, потому что «docker run», кажется, ожидает одной команды и отдельных аргументов без кавычек, а не строки в кавычках.
davidA
@meowsqueak: в этом ответе рассказывается, как запускать несколько команд внутри уже созданного и запущенного контейнера без входа в этот контейнер, что полезно для автоматизации. Однако, если вы хотите запустить несколько команд во время создания контейнера (команда PS: docker run создает и запускает контейнер), вы можете добиться этого, следуя ответам в том же потоке stackoverflow.com/a/41363989/777617
Cyclops
Вместо этого cmd1мне нужно передать весь цикл for, но он ожидает ;после оператора цикла и оператора do . Как я могу запустить весь для цикла как одной команды , т.е. cmd1? Является ли это возможным?
Nicholas K
19

Я искал ответ на тот же вопрос и нашел для себя ENTRYPOINT в решении Dockerfile .

Dockerfile

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

Теперь скрипты выполняются, когда я запускаю контейнер, и я получаю приглашение bash после того, как скрипты были выполнены.

Tojo
источник
6

Вы также можете смонтировать локальный каталог в свой образ докера и создать скрипт в своем .bashrc. Не забывайте, что сценарий должен состоять из функций, если вы не хотите, чтобы он выполнялся в каждой новой оболочке. (Это устарело, см. Уведомление об обновлении.)

Я использую это решение, чтобы иметь возможность обновлять скрипт вне экземпляра докера. Таким образом, мне не нужно повторно запускать изображение в случае изменений, я просто открываю новую оболочку. (Избавился от повторного открытия оболочки - см. Уведомление об обновлении)

Вот как вы привязываете свой текущий каталог:

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

Теперь ваш текущий каталог привязан к /scriptsвашему экземпляру докера.

(Устарело) Чтобы сохранить .bashrcизменения, зафиксируйте рабочий образ с помощью этой команды:

docker commit $container_id $my_docker_build

Обновить

Чтобы решить проблему, чтобы открывать новую оболочку для каждого изменения, я сейчас делаю следующее:

В самом dockerfile добавляю RUN echo "/scripts/bashrc" > /root/.bashrc". Внутри zshrcя экспортирую директорию скриптов по пути. Каталог скриптов теперь содержит несколько файлов вместо одного. Теперь я могу напрямую вызывать все сценарии, не открывая вспомогательную оболочку при каждом изменении.

Кстати, вы также можете определить файл истории за пределами вашего контейнера. Таким образом, больше не нужно фиксировать изменение bash.

Девпул
источник
Слишком поздно..! @javier уже показывает прямое решение !! Я чувствую, что еще лучше.
zappy
2
@zappy решение от javier не решило эту проблему удобно для меня, но мое решение помогло, я подумал, что это будет интересно для тех, у кого есть аналогичная проблема, когда они не хотят перезапускать изображения докеров для обновления просмотреть необходимые им функции. Например, если вы используете несколько образов докеров одновременно для запуска кластера разработки, вы не хотите перезапускать их все время.
Devpool
3

Если вы не хотите (или имеете) работающий контейнер, вы можете вызвать свой скрипт напрямую с помощью runкоманды.

Удалите итеративные -i -tаргументы tty и используйте это:

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

Это будет (не тестировалось) также работать для других скриптов:

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py
Томио
источник
0

Если вы хотите запустить одну и ту же команду в нескольких экземплярах, вы можете сделать это:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
DMin
источник