#docker
Вопрос:
У меня есть запущенный контейнер Docker, и мне нужно запустить сеанс интерактивной оболочки внутри контейнера и выполнить несколько команд внутри до этого. Как я могу это сделать?
Я пытался
docker exec -it foo bash < my_commands_to_exexute_inside_the_container.sh
и
docker run foo bash -c "echo Foo;echo Bar"
Но ничего из этого не работает. Первый не выполняет команды из скрипта, а второй делает это, но закрывает сеанс терминала.
Есть идеи? Кстати: Команды должны поступать извне контейнера. В контейнере нет файла с этими командами.
Редактировать:
Следующее делает почти точно то, что я хочу. Единственная загвоздка в том, что первая команда закрывает оболочку, а вторая команда открывает ее снова. Это приводит к тому, что я теряю переменные среды.
docker exec -i foo bash < "cli.sh"
docker exec -it foo bash
Есть ли какой-либо способ добиться такого поведения, не закрывая оболочку между ними?
Комментарии:
1. Какой основной процесс выполняется в контейнере? Если бы этот процесс не находился внутри контейнера, как бы вы получили интерактивную оболочку внутри процесса?
2. Я не понимаю вашего вопроса, сри.
Ответ №1:
Введите -t
свою первую команду (вы запускаете сценарий, не взаимодействуя с командной строкой вручную, поэтому вам не нужно выделять TTY).:
docker exec -i foo bash < my_commands_to_exexute_inside_the_container.sh
Например, если я запускаю контейнер Fedora:
docker run -d --name shell fedora:34 sleep inf
И у меня есть файл mycommands.sh
со следующим содержимым:
echo "The time is $(date)"
echo "This system is: $(uname -a)"
Я могу выполнить эту оболочку в контейнере следующим образом:
$ docker exec -i shell bash < mycommands.sh
The time is Sat Jul 31 12:37:59 UTC 2021
This system is: Linux 50715db46e9b 5.12.14-300.fc34.x86_64 #1 SMP Wed Jun 30 18:30:21 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Комментарии:
1. Спасибо за ваш ответ! Но это закроет сеанс интерактивной оболочки. Если я выполню это, я окажусь за пределами контейнера. Как я могу держать оболочку внутри контейнера открытой?
2. Мне не совсем ясно, какова ваша цель здесь. Контейнер будет продолжать работать, поэтому любая команда, которую вы использовали в своей
docker run
команде, будет продолжать выполняться. Я использовалsleep inf
здесь, но вместо этого вы могли бы запустить интерактивную оболочку, хотя в этом нет особого смысла (я думаю, вы моглиdocker attach
бы это сделать). Как бы вы этого добились, если бы Докер не был замешан? В большинстве оболочек либо (а) вы запускаете интерактивный сеанс, либо (б) вы передаете команды в stdin, и оболочка завершает работу, когда завершает выполнение сценария.3. @DarkMath Я полагаю, что вы могли бы привязать файл сценария оболочки к контейнеру, а затем запустить
docker exec -it runningContainer bash
и выполнить этот файл, как только окажетесь внутри. После этого приглашение bash будет просто сидеть там бесконечно долго, ожидая вас.4. @DarkMath Имейте в виду, что контейнеры не могут оставаться без причины. Они не могут просто сидеть и ничего не делать. Контейнер предназначен для выполнения чего-то, например, процесса веб-сервера. Если он ничего не делает, он просто выходит.