如何进入Docker容器的外壳?


1160

我开始使用Docker。我正在使用WordPress基本映像和docker-compose。

我正在尝试使用ssh进入其中一个容器,以检查在初始构建期间创建的文件/目录。我试着跑步docker-compose run containername ls -la,但是没有做任何事情。即使这样做,我还是希望有一个可以遍历目录结构的控制台,而不是运行单个命令。用Docker执行此操作的正确方法是什么?


所以听起来答案就是docker attach。但是如何从docker-compose做到这一点呢?
安德鲁

3
使用docker exec askubuntu.com/a/543057/35816。使用docker ps
Mauricio Scheffer,2015年

26
sudo docker run -it --entrypoint /bin/bash <container_name>使您以交互方式进入容器。然后可以使用检查在容器中的文件系统cd <path>
谢尔盖

Answers:


1728

docker attach将允许您连接到Docker容器,但这与并不是真的一样ssh。例如,如果您的容器正在运行Web服务器,docker attach则可能会将您连接到Web服务器进程的标准输出。它不一定会给您外壳。

docker exec命令可能正是您要寻找的;这将使您可以在现有容器中运行任意命令。例如:

docker exec -it <mycontainer> bash

当然,您正在运行的任何命令都必须存在于容器文件系统中。

在上面的命令中<mycontainer>是目标容器的名称或ID。是否使用都没关系docker compose; 只需运行docker ps并使用ID(在第一列中显示一个十六进制字符串)或名称(在最后一列中显示)即可。例如,给定:

$ docker ps
d2d4a89aaee9        larsks/mini-httpd   "mini_httpd -d /cont   7 days ago          Up 7 days                               web                 

我可以跑:

$ docker exec -it web ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
18: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:3/64 scope link 
       valid_lft forever preferred_lft forever

我可以通过运行以下命令完成同一件事:

$ docker exec -it d2d4a89aaee9 ip addr

同样,我可以在容器中启动外壳程序。

$ docker exec -it web sh
/ # echo This is inside the container.
This is inside the container.
/ # exit
$

76
另外,docker exec仅适用于运行中的容器(否则使用docker run -it --entrypoint /bin/bash或类似的容器)。
L0j1k 2015年

59
为了您的方便,-it是一个组合-i-t--interactive(“保持STDIN打开即使没有连接”)分别--tty(“分配伪TTY”)。
AdrianFöder17年

23
在基于Alpine Linux的容器上,您可能没有bash,因此,请使用sh代替。
罗宾·格林

9
@ L0j1k是docker run -it --entrypoint /bin/bash <imageid> --any --more --args为了向人们澄清
Alexander Mills

2
@AlexanderMills是的,为了进一步澄清,--any --more --args您所拥有的将被馈送到映像中定义的映像,CMD而不是Docker(或者,如果映像仅定义an ENTRYPOINT和no CMD,那么这些选项将被馈送到/bin/bash您在此处指定的位置)。因此,例如,其他任何docker run选项(例如--net "host")都需要放在之前<imageid>
L0j1k

302

要将bash放入正在运行的容器中,请输入以下命令:

docker exec -t -i container_name /bin/bash

要么

docker exec -ti container_name /bin/bash

要么

docker exec -ti container_name sh

假设它是Linux容器?
彼得·莫滕森

5
/斌/庆典wasnt只需要bash的为我做
阿南德VARKEY飞利浦

6
我希望docker exec -it代替docker exec -t -i
VaTo


@AATHITHRAJENDRANI只是更喜欢命令的较短形式,而不是具有两个标志,您可以在同一参数-it中包含这两个选项。
VaTo19年

85

假设由于您自己的原因,您确实确实想使用SSH。这需要一些步骤,但是可以做到。这是您将在容器内运行以对其进行设置的命令...

apt-get update
apt-get install openssh-server

mkdir /var/run/sshd
chmod 0755 /var/run/sshd
/usr/sbin/sshd

useradd --create-home --shell /bin/bash --groups sudo username ## includes 'sudo'
passwd username ## Enter a password

apt-get install x11-apps ## X11 demo applications (optional)
ifconfig | awk '/inet addr/{print substr($2,6)}' ## Display IP address (optional)

现在,您甚至可以使用X11转发到SSH客户端来运行图形应用程序(如果它们已安装在容器中):

ssh -X username@IPADDRESS
xeyes ## run an X11 demo app in the client

以下是一些相关资源:


33

如果您像我一样在这里寻找特定于Docker Compose的答案,它提供了一种简便的方法,而无需查找生成的容器ID。

docker-compose exec根据您的docker-compose.yml文件获取服务的名称。

因此,要为您的“ Web”服务获取Bash shell,您可以执行以下操作:

$ docker-compose exec web bash

docker-compose run如果您的容器尚不存在,也可以使用。
保罗

23

注意:此答案将促进我编写的工具。

我创建了一个容器化的SSH服务器,您可以将其“粘贴”到任何正在运行的容器。这样,您可以为每个容器创建合成。唯一的要求是容器具有Bash。

以下示例将启动连接到名称为“ my-container”的容器的SSH服务器。

docker run -d -p 2222:22 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e CONTAINER=my-container -e AUTH_MECHANISM=noAuth \
  jeroenpeeters/docker-ssh

ssh localhost -p 2222

当您通过选择的SSH客户端连接到该SSH服务时,将在名称为“ my-container”的容器中启动Bash会话。

有关更多指针和文档,请参见:https : //github.com/jeroenpeeters/docker-ssh


1
真是太好了。这样做的最大好处是您将获得功能齐全的终端。当我使用“ docker exec”方法时,我无法清除终端内容,less每次运行时都会显示警告,等等。到目前为止,使用Jeroen的容器为我提供了更好的体验。只要确保检查出文档即可。响应中的样本命令似乎不再有效。
拉斐尔·G.16年

1
这是一个很棒的工具。您知道我如何将其用作jenkins管道docker代理吗?我希望jenkins通过SCP将某些文件传输到远程主机并使用SSH执行它们
Gilson,

21

如果您在Windows上使用Docker并希望获得对容器的Shell访问权限,请使用以下命令:

winpty docker exec -it <container_id> sh

最有可能的是,您已经安装了Git Bash如果不这样做,请确保安装它。


1
假设一个Linux Docker容器?
彼得·莫滕森

1
docker exec -ti <container_id> cmd运行良好
PBo

17

如果容器已经退出(可能是由于某些错误),则可以执行

$ docker run --rm -it --entrypoint /bin/ash image_name

要么

$ docker run --rm -it --entrypoint /bin/sh image_name

要么

$ docker run --rm -it --entrypoint /bin/bash image_name

创建一个新容器并放入一个外壳。由于您指定了--rm,因此退出外壳程序时将删除该容器。


16

在某些情况下,您的图片可能基于Alpine。在这种情况下,它将抛出:

OCI运行时exec失败:exec失败:container_linux.go:348:启动容器进程导致“ exec:\” bash \”:在$ PATH中找不到可执行文件”:未知

因为/bin/bash不存在。代替此,您应该使用:

docker exec -it 9f7d99aa6625 ash

要么

docker exec -it 9f7d99aa6625 sh

15

使用以下命令通过SSH进入Docker容器:

sudo docker exec -i -t (container ID) bash


11

很简单

列出所有Docker映像:

sudo docker images

在我的系统上,它显示以下输出:

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
bash                latest              922b9cc3ea5e        9 hours ago
14.03 MB
ubuntu              latest              7feff7652c69        5 weeks ago         81.15 MB

我的PC上有两个Docker映像。假设我要运行第一个。

sudo docker run -i -t ubuntu:latest /bin/bash

这将使您可以对容器进行终端控制。现在,您可以在容器内执行所有类型的Shell操作。就像这样做ls会在文件系统的根目录中输出所有文件夹。

bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

11

要检查文件,请运行docker run -it <image> /bin/sh以获取交互式终端。可以通过获取图像列表docker images。与docker exec该解决方案相反,在图像不启动(或在运行后立即退出)的情况​​下也可以使用。


假设有Linux Docker映像?
彼得·莫滕森

10

最佳解决方案

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

sudo npm install -g goinside

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

goinside docker_container_name

旧答案

我们已将以下代码段放入~/.profile

goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside

这不仅使每个人都可以使用以下方法进入正在运行的容器中:

goinside containername

它还解决了有关固定Docker容器终端大小的长期存在的问题。如果您面对它,那将非常烦人。

另外,如果您单击链接,您的Docker容器名称也将具有命令完成功能。


1
谢谢。至少对于那些已经包含bash的图像而言,它就像一种魅力。可能不适用于基于高山图像工作,但是,可以是固定的与不同的功能专门为SH /灰等写入
拉夫巴斯卡尔

8
$ docker exec -it <Container-Id> /bin/bash

或者取决于外壳,它可以是

$ docker exec -it <Container-Id> /bin/sh

您可以通过命令获取container-Iddocker ps

-i =互动

-t =分配伪TTY


8

我创建了一个终端功能,以更轻松地访问容器的终端。也许对你们也有用:

因此,结果是,而不是键入:

docker exec -it [container_id] /bin/bash

你会写:

dbash [container_id]

将以下内容放入〜/ .bash_profile(或其他适用于您的内容)中,然后打开一个新的终端窗口并享受快捷方式:

#usage: dbash [container_id]
dbash() {
    docker exec -it "$1" /bin/bash
}

7

您可以通过传递选项-ti与docker容器中的终端进行交互

docker run --rm -ti <image-name>
eg: docker run --rm -ti ubuntu

-t代表终端-i代表互动


6

docker exec肯定是一个解决方案。处理您所问问题的一种简单方法是将Docker内部的目录挂载到本地系统的目录中

这样您可以立即查看本地路径中的更改。

docker run -v /Users/<path>:/<container path> 

1
您的命令实际上是将主机目录装载到容器中。
Demonbane

是的 备份到另一个目录,然后挂载该卷,然后将备份移动到已挂载的文件夹。
Pratik

6

采用:

docker attach <container name/id here>

尽管有危险,但另一种方法是使用attach,但是如果您Ctrl+ C退出会话,则也将停止容器。如果您只想查看发生了什么,请使用docker logs -f

:~$ docker attach --help
Usage:  docker attach [OPTIONS] CONTAINER

Attach to a running container

Options:
      --detach-keys string   Override the key sequence for detaching a container
      --help                 Print usage
      --no-stdin             Do not attach STDIN
      --sig-proxy            Proxy all received signals to the process (default true)


4

如果您的Docker安装了Kitematic,则可以使用GUI。Kitematic从Docker图标打开,然后在Kitematic窗口中选择您的容器,然后单击该exec图标。

您也可以在此GUI中查看容器日志和许多容器信息(在“设置”选项卡中)。

从菜单中选择Kitematic

点击执行


2

就我而言,由于某些原因,我需要检查每个容器中所有与网络有关的信息。因此以下命令在容器中必须有效...

ip
route
netstat
ps
...

我检查了所有这些答案,没有一个对我有帮助。我在其他网站上搜索了信息。我不会在此处添加超级链接,因为它不是用英语编写的。因此,我只为与我有相同要求的人员提供了摘要解决方案。

假设您有一个名为light-test的运行容器。请按照以下步骤操作。

  • docker inspect light-test -f {{.NetworkSettings.SandboxKey}}。该命令将得到类似的回复/var/run/docker/netns/xxxx
  • 然后ln -s /var/run/docker/netns/xxxx /var/run/netns/xxxx。该目录可能不存在,mkdir /var/run/netns请先执行。
  • 现在您可以执行ip netns exec xxxx ip addr show以探索容器中的网络世界。

PS。xxxx总是从第一个命令收到的值相同。当然,任何其他命令都是有效的,即ip netns exec xxxx netstat -antp|grep 8080


1

另一种选择是使用nsenter

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

2
出现许多问题nsenter。首先是它要求您具有对Docker主机的物理访问权,而这并不是给定的(您可能正在使用远程Docker API)。此外,在nsenterUnix 下运行可以使您不受Docker施加的一些安全和资源限制(根据您的环境,它可以是优点还是缺点)。
larsk 2015年

1
甚至nsenter的作者都说要使用docker exec这些天。
L0j1k 2015年

1
@larsks是的,两者都有自己的好处。例如,是nsenter的优势docker execdocker exec在我看来更优雅。
xuhdev 2015年

2
@ L0j1k只是为了减少混乱:您所引用的帖子不是nsenter的作者,而是运行nsenter的Docker映像的作者。
xuhdev 2015年

1

如果您使用的是Docker Compose,那么它将带您进入Docker容器。

docker-compose run container_name /bin/bash

在容器内部,它将带您到Dockerfile中定义的WORKDIR。您可以通过以下方式更改工作目录

WORKDIR directory_path # E.g  /usr/src -> container's path

0

执行到一个正在运行的容器中 test,下面是以下命令

如果容器有bash

docker exec -it test /bin/bash

如果容器有bourne外壳并且大多数情况下都存在

docker run -it test /bin/sh

-3

对于docker-compose up(Docker4Drupal)

docker-compose exec php bash

我在Linux笔记本电脑上将Docker用于Drupal。运行容器后,我使用' docker-compose exec php bash'与容器连接,以便可以运行drush突击队。这对我来说可以。

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.