Как выполнить несколько команд в контейнере Docker и оставить сеанс оболочки открытым?

#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 Имейте в виду, что контейнеры не могут оставаться без причины. Они не могут просто сидеть и ничего не делать. Контейнер предназначен для выполнения чего-то, например, процесса веб-сервера. Если он ничего не делает, он просто выходит.