如何在后台模式下将bash或ssh放入正在运行的容器中?


933

我想ssh或bash到正在运行的docker容器中。请参见示例:

$ sudo docker run -d webserver
webserver is clean image from ubuntu:14.04
$ sudo docker ps
CONTAINER ID  IMAGE            COMMAND    CREATED STATUS  PORTS          NAMES
665b4a1e17b6  webserver:latest /bin/bash  ...     ...     22/tcp, 80/tcp loving_heisenberg 

现在我想得到这样的东西(进入正在运行的容器):

$ sudo docker run -t -i webserver (or maybe 665b4a1e17b6 instead)
$ root@665b4a1e17b6:/# 
However when I run the line above I get new CONTAINER ID
$ root@42f1e37bd0e5:/#

我使用了Vagrant,并且希望获得与相似的行为vagrant ssh


或者sudo docker exec -i -t 665b4a1e17b6 /bin/sh能够安装apt程序和软件包
fonjeekay

1
请注意,使用SSH将bash放入运行中的容器是不好的做法–请参阅此处的基本原理sudo docker exec -i -t container-name /bin/bash是一条路。
patryk.beza

Answers:


1306

答案是Docker的attach命令。因此,对于上面的示例,解决方案将是:

$ sudo docker attach 665b4a1e17b6 #by ID
or
$ sudo docker attach loving_heisenberg #by Name
$ root@665b4a1e17b6:/#

对于Docker 1.3或更高版本:感谢用户WiR3D提出了另一种获取容器外壳的方法。如果使用,attach则只能使用一个shell实例。因此,如果要使用容器外壳的新实例打开新终端,则只需运行以下命令:

$ sudo docker exec -i -t 665b4a1e17b6 /bin/bash #by ID

要么

$ sudo docker exec -i -t loving_heisenberg /bin/bash #by Name
$ root@665b4a1e17b6:/#

5
或者,执行sudo docker attach loving_heisenberg
Thiago Perrotta 2014年

51
attach命令对我不起作用,它使docker冻结..任何想法为什么会发生?
Mo J. Mughrabi 2014年

10
提醒boot2docker用户:删除sudo :)
Henno 2014年

17
-i -t等于-it
pasha.zhukov

47
这是一个危险的答案,需要选择并予以高度评价。 docker attach例如,访问MongoDB实例将杀死该实例。如在更详细的解释了这个问题 attach,并exec为不同的动物。
fwc

675

从Docker 1.3开始:

docker exec -it <containerIdOrName> bash

基本上,如果Docker容器是使用/bin/bash命令启动的,则可以使用进行访问attach。如果不是,那么您需要执行命令以使用创建容器内的Bash实例exec

同样要退出Bash而不使Bash在恶意进程中运行:

exit

是的,就是这么简单。


仍未弄清楚如何使纳米工作。认为可能涉及来自phusion的
docker

有没有办法在dockers中默认设置bash?
ipeacocks 2015年

@ipeacocks是的,如果dockerfile中的RUN命令是/bin/bash。但是要看你的意思。如果您想运行该容器并在同一终端上立即使用bash,则-it应该使用运行该容器
WiR3D 2015年

10
使用码头工人组是一个坏习惯。本质上,在docker组中的任何用户都具有root权限,而无需使用sudo。projectatomic.io/blog/2015/08/...
Maiku森

1
从主机安全的角度来看,我认为是否使用sudovs docker组并没有多大区别。无论哪种方式,泊坞窗都内置了一个安全漏洞,无论您使用泊坞窗组还是sudo启动容器,该漏洞都可以从来宾在主机文件系统中提供全部特权。
nobar

123

尽管问题的作者明确表示他们对正在运行的容器感兴趣,但是也值得注意的是,如果容器未运行,那么您可以运行它以进行运行:

docker run -i -t --entrypoint /bin/bash <imageID>


10
就像@kraxor的答案一样,这提供了一个不同的容器。
Blaisorblade 2015年


19

基于@Timur的答案,我创建了以下方便的脚本

设定

docker-ssh文件放入$PATH以下内容

#!/bin/bash -xe

# docker container id or name might be given as a parameter
CONTAINER=$1

if [[ "$CONTAINER" == "" ]]; then
  # if no id given simply just connect to the first running container
  CONTAINER=$(docker ps | grep -Eo "^[0-9a-z]{8,}\b")
fi

# start an interactive bash inside the container
# note some containers don't have bash, then try: ash (alpine), or simply sh
# the -l at the end stands for login shell that reads profile files (read man)
docker exec -i -t $CONTAINER bash -l

注意:某些容器不包含bash,而是ashsh等等。在这些情况下,bash应在以上脚本中替换它们。

用法

如果只有一个正在运行的实例,只需运行

$> docker-ssh 

否则,向其提供您从docker ps(第一列)获得的docker id参数

$> docker-ssh 50m3r4nd0m1d

我可以知道为什么我们最后需要-l吗?
Nam G VU

启动bash作为登录外壳,读取环境参数(在命令上方的行中进行了描述)
Matyas

12

如果您的容器未安装bash,则可以尝试sh:

docker exec -it CONTAINER /bin/sh

或先在/ bin中寻找shell:

docker export CONTAINER|tar -t|egrep ^bin/

什么是“领事”?您有参考吗?你是说“控制台”吗?
彼得·莫滕森

9

我创建了一个容器化的SSH服务器,该服务器为所有运行中的容器提供SSH功能。您无需更改容器。唯一的要求是该容器具有bash。

如果您有一个名为“ web-server1”的容器。以下docker run命令将启动第二个容器,该容器将为第一个容器提供SSH。

docker run -ti --name sshd-web-server1 -e CONTAINER=web-server1 -p 2222:22 \
-v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker \
jeroenpeeters/docker-ssh

有关更多指针,查看https://github.com/jeroenpeeters/docker-ssh


这应该是公认的答案^
Nam G VU

顺便说一句,当使用您的解决方案启动ssh会话时,如何自动加载.bashrc?还在github github.com/jeroenpeeters/docker-ssh/issues/30
Nam G VU

6

@jpetazzo 关于这个主题有一个很棒的帖子。简短的答案是使用nsenter

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

PS:别忘了查看帖子评论中的讨论...

干杯


1
那是一个相当老的帖子,不再需要。@ WiR3D的docker exec解决方案更加方便。
drevicko

4

您还可以使用Pipework为Docker容器提供可路由的IP地址,然后在SSH中使用该新IP地址进入计算机。

这将是更“传统的”(ssh),而不是使用诸如的应用程序特定命令docker attach,最终将使其在系统和版本之间更加“便携”。


请添加简单的方法。老实说,我确实很需要它,但是我没有时间为此寻找最简单的解决方案。你能在这里发表你的答案吗?这将是伟大的..
铁木尔Fayzrakhmanov

2
有两种方法可以完成此操作,但这并不简单,并且可能会成为大篇幅的文章。您可以自己查看此链接,以使用管道工作或该链接,女巫基本上完成了与管道工作相同的工作,并且更加简单,但是您需要手动进行操作。因此,这取决于要谈话的服务器数量。如果您找不到更具体的信息,请告诉我。但是我也没有时间写完整的教程。
radriaanse 2014年

你是对的-没有明显的和简单的方式来做到这一点(谢谢你的链接,我想以后我会重新考虑。
铁木尔Fayzrakhmanov



1

进去

使用以下goinside命令安装命令行工具:

sudo npm install -g goinside

并进入具有适当终端大小的docker容器,其中包含:

goinside docker_container_name

有关更多详细信息,请查看



0

仅供参考。如果需要登录不是守护程序的简单容器,则需要使用以下命令:

docker start {id}
docker attach {id}

-1

如果容器停止了,例如仅数据容器,那么一个好的解决方案是每次要附加到数据容器时都运行一个一次性容器。在这种情况下,数据容器本身可能完全是空的,因为临时容器将具有OS工具。

$ docker run --rm --volumes-from mydata -it ubuntu bash
root@645045d3cc87:/# ls /mydata
root@645045d3cc87:/# touch /mydata/foo
root@645045d3cc87:/# exit
exit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.