Можно ли запустить сеанс оболочки в работающем контейнере (без ssh)

341

Я наивно ожидал, что эта команда запустит оболочку bash в работающем контейнере:

docker run "id of running container" /bin/bash

похоже, что это невозможно, я получаю сообщение об ошибке:

2013/07/27 20:00:24 Internal server error: 404 trying to fetch remote history for 27d757283842

Итак, если я хочу запустить bash shell в работающем контейнере (например, в целях диагностики)

я должен запустить SSH сервер и войти через ssh?

Макс Л.
источник
1
docker run CONTAINERпланируется в 1.0
колыпто
7
Начиная с докера 1.3, вы действительно должны делать то, что описано в этом ответе
Thomasleveil
1
простоdocker attach container_name
maxbellec
1
Кажется, что второй ответ намного лучше, чем принятый - вы могли бы пересмотреть вопрос об изменении принятого ответа?
jsbueno

Ответы:

285

РЕДАКТИРОВАТЬ: Теперь вы можете использовать docker exec -it "id of running container" bash( док )

Ранее ответ на этот вопрос был:

Если вам действительно нужно и вы находитесь в среде отладки, вы можете сделать это: sudo lxc-attach -n <ID> Обратите внимание, что идентификатор должен быть полным ( docker ps -notrunc).

Тем не менее, я настоятельно рекомендую против этого.

уведомление: -notruncустарело, скоро будет заменено --no-trunc.

creack
источник
1
почему вы рекомендуете против этого?
Макс Л.
7
Я рекомендую против этого, потому что 1) для него требуется самое последнее ядро, 2) вы делаете что-то вне докера, поэтому вы не сможете его отслеживать (журналы, вложения и т. Д.). Кроме того, докер может использовать lxc прямо сейчас, но нет никаких гарантий, что он будет действовать вечно.
13
1
Попробуйте обновить до 0.7.6. Docker все еще использует lxc прямо сейчас и lxc-attachдолжен нормально работать. Я только что проверил дважды, и это работает для меня. (Обратите внимание, что он не будет работать с ядром до 3.8).
creack
2
с 0.9 докер больше не работает с LXC по умолчанию. Вам бы пришлось запустить докер docker -d -e lxc
Дэймон
2
Макс Л., ваш вариант использования может быть решен с объемами данных . Не тестировался пример: 1) запустить контейнер с Nginx бревен в объеме данных: docker run -v /var/log/nginx -name somename imagename command; 2) запустить другой контейнер для просмотра содержимого тома данных: docker run -volumes-from somename -i -t busybox /bin/sh.
ciastek
615

В докере 1.3 появилась новая команда docker exec. Это позволяет вам войти в работающий докер:

docker exec -it "id of running container" bash
Michael_Scharf
источник
2
Это отлично сработало для меня. Очень полезное дополнение к Docker Run.
oraserrata
Что если я внес изменения во время выполнения запущенного контейнера и хотел отразить изменения в сети? что такое лучшие практики?
mediaroot
Очень полезно. Спасибо вам
luongnv89
использовать, docker psчтобы получить идентификатор запущенных экземпляров
мюон
Примечание. Контейнер может не иметь bash (»exec:« bash »: исполняемый файл не найден«). Используйте, docker inspect <image>чтобы увидеть, какая оболочка доступна. Например, беги docker exec -it <container id> /bin/shвместо этого.
pixelbrackets
14

Просто сделать

docker attach container_name

Как уже упоминалось в комментариях, чтобы отсоединиться от контейнера, не останавливая его, введите Ctrlpзатем Ctrlq.

maxbellec
источник
5
Спасибо!! Это помогло. И в контексте актуального вопроса я бы хотел кое-что добавить. После отладки нашего контейнера , используя, docker attach container_nameиспользовать ctrl pи ctrl qвместо exit. exitкоманда останавливает контейнер, где , как ctrlpи ctrl qпросто отрывает этот контейнер и держит это работает
феникс
10

Так как вещи накапливаются, на данный момент используется рекомендуемый способ доступа к работающему контейнеру nsenter.

Вы можете найти больше информации об этом github-хранилище . Но в целом вы можете использовать nsenter следующим образом:

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid

или вы можете использовать обертку docker-enter:

docker-enter <container_name_or_ID>

Хорошее объяснение по этой теме можно найти в записи блога Жерома Петаццони: почему вам не нужно запускать sshd в ваших док-контейнерах

Teudimundo
источник
к сожалению, переменные env путаются с использованием этого подхода (если вы хотите проверить переменные, созданные по ссылке). Я предлагаю сделать source /proc/*/environ.
Томас Томечек
8

Первое, что вы не можете запустить

docker run "existing container" command

Потому что эта команда ожидает изображение, а не контейнер, и это в любом случае приведет к появлению нового контейнера (поэтому не тот, на который вы хотели посмотреть)

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

Я запускаю свои команды через супервизора в режиме DEAMON.

Затем я выполняю то, что я называю docker_loop.sh . Содержание в значительной степени таково:

#!/bin/bash
/usr/bin/supervisord
/usr/bin/supervisorctl
while ( true )
    do
    echo "Detach with Ctrl-p Ctrl-q. Dropping to shell"
    sleep 1
    /bin/bash
done

Что он делает, так это то, что он позволяет вам «прикрепиться» к контейнеру и получить supervisorctlинтерфейс для остановки / запуска / перезапуска и проверки журналов. Если этого не достаточно, вы можете Ctrl+Dзаскочить в оболочку, которая позволит вам взглянуть вокруг, как если бы это была обычная система.

ПОЖАЛУЙСТА, ПОЖАЛУЙСТА, ПРИНИМАЙТЕ ВНИМАНИЕ, что эта система не так безопасна, как контейнер без оболочки, поэтому примите все необходимые меры для защиты вашего контейнера.

Alessandro
источник
5

Следите за этим запросом на получение доступа: https://github.com/docker/docker/pull/7409

Который реализует предстоящую docker exec <container_id> <command>утилиту. Когда это доступно, должна быть возможность, например, запускать и останавливать службу ssh внутри работающего контейнера.

Для этого также nsinitнеобходимо сделать следующее: «nsinit предоставляет удобный способ доступа к оболочке внутри пространства имен запущенного контейнера» , но запускать его выглядит сложно. https://gist.github.com/ubergarm/ed42ebbea293350c30a6

Фос
источник
docker execприземлился в Docker 1.3, так что теперь можно создавать и присоединять новый сеанс оболочки в работающем контейнере
foz
3

Ты можешь использовать

docker exec -it <container_name> bash
antikytheraton
источник
1

На самом деле есть способ иметь оболочку в контейнере.

Предположим, что вы /root/run.shзапускаете процесс, менеджер процессов (супервизор) или что-то еще.

Создайте /root/runme.shс некоторыми хитростями gnu-screen:

# Spawn a screen with two tabs
screen -AdmS 'main' /root/run.sh
screen -S 'main' -X screen bash -l
screen -r 'main'

Теперь у вас есть демоны на вкладке 0 и интерактивная оболочка на вкладке 1. В docker attachлюбое время вы можете увидеть, что происходит внутри контейнера.

Другой совет - создать изображение «комплекта разработки» поверх рабочего образа со всеми необходимыми инструментами, включая этот трюк с экраном.

kolypto
источник
1

вот мое решение

часть DOckerfile:

...
RUN mkdir -p /opt
ADD initd.sh /opt/
RUN chmod +x /opt/initd.sh
ENTRYPOINT ["/opt/initd.sh"]

часть "initd.sh"

#!/bin/bash
...
/etc/init.d/gearman-job-server start
/etc/init.d/supervisor start
#very important!!!
/bin/bash

после построения изображения у вас есть два варианта использования exec и attach:

  1. с exec (который я использую), запустите:

запуск докера - имя $ CONTAINER_NAME -dt $ IMAGE_NAME

затем

docker exec -it $ CONTAINER_NAME / bin / bash

и использовать

CTRL + D, чтобы отделить

  1. с приложением запустите:

запуск докера - имя $ CONTAINER_NAME -dit $ IMAGE_NAME

затем

докер присоединить $ CONTAINER_NAME

и использовать

CTRL + P и CTRL + Q, чтобы отсоединить

разница между параметрами в параметре -i

Тим
источник
1

Есть два способа.

С прикрепленным

$ sudo docker attach 665b4a1e17b6 #by ID

С exec

$ sudo docker exec - -t 665b4a1e17b6 #by ID
gurubelli
источник
0

Полезно назначать имя при запуске контейнера. Вам не нужно ссылаться на container_id.

docker run --name container_name yourimage docker exec -it container_name bash

Мацумото Казуя
источник
0

во-первых, получите идентификатор контейнера желаемого контейнера с помощью

docker ps

вы получите что-то вроде этого:

CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                          PORTS                    NAMES
3ac548b6b315        frontend_react-web     "npm run start"     48 seconds ago      Up 47 seconds                   0.0.0.0:3000->3000/tcp   frontend_react-web_1

Теперь скопируйте этот идентификатор контейнера и выполните следующую команду:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh

Umesh
источник
-2

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

Контейнеры, как и любой другой процесс. На самом деле вы можете захотеть «присоединиться» к ним для целей отладки (подумайте о / proc // env или strace -p), но это очень особый случай.

Обычно вы просто «запускаете» процесс, поэтому, если вы хотите изменить конфигурацию или прочитать журналы, просто создайте новый контейнер и убедитесь, что вы записываете журналы вне его, разделяя каталоги, записывая в stdout (чтобы работали журналы докера) или что-то вроде того.

В целях отладки вы можете запустить оболочку, затем код, а затем нажать CTRL-p + CTRL-q, чтобы оставить оболочку нетронутой. Таким образом, вы можете подключить, используя:

docker attach <container_id>

Если вы хотите отладить контейнер, потому что он делает что-то, чего вы не ожидали, попробуйте отладить его: /server/596994/how-can-i-debug-a-docker-container -initialization

estani
источник
Это совершенно неправильно. Возможность проанализировать пространство имен LXC, в котором выполняется ваше приложение, - это не «особый случай», это обычное / ежедневное занятие для любого разработчика.
сонный
@sleepycal "любой разработчик" звучит немного предвзято. В любом случае я использую самоанализ процессов, поэтому то же самое относится и к контейнерам. Это идея отладки. Вы присоединяете к процессу отладчик (который может иметь кли). Думая, что вы "вошли" в контейнер, звучит все еще обманчиво для меня.
Эстани
-4

Нет, это невозможно. Используйте что-то вроде supervisordполучения ssh-сервера, если это необходимо. Хотя я определенно подвергаю сомнению необходимость.

Ник Стинамантес
источник