我如何进入Docker容器的shell?

How do I get into a Docker container's shell?

我要开始和Docker合作了。我使用的是WordPress基本图像和Docker撰写。

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


docker attach可以让你连接到你的码头集装箱,但这与ssh不是一回事。例如,如果容器运行的是Web服务器,那么docker attach可能会将您连接到Web服务器进程的stdout。它不一定给你一个壳。

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

1
docker exec -it <mycontainer> bash

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

在上面的命令中,是目标容器的名称或ID。不管您是否使用docker compose;只需运行docker ps,并使用ID(显示在第一列中的十六进制字符串)或名称(显示在最后一列中)。例如,给出:

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

我可以跑:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ 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

我可以通过跑步来完成同样的事情:

1
$ docker exec -it d2d4a89aaee9 ip addr

同样,我可以在容器中启动一个外壳;

1
2
3
4
5
$ docker exec -it web sh
/ # echo This is inside the container.
This is inside the container.
/ # exit
$


要撞击正在运行的容器,请键入以下内容:

1
docker exec -t -i container_name /bin/bash


比如说,出于您自己的原因,您确实想要使用ssh。这需要几个步骤,但可以做到。以下是您将在容器中运行的命令,用于设置容器…

1
2
3
4
5
6
7
8
9
10
11
12
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客户机来运行图形应用程序(如果它们安装在容器中):

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

以下是一些相关资源:

  • OpenSSH服务器未在Docker容器中启动
  • 如何在后台模式下将bash或ssh放入正在运行的容器中?
  • 可以在Docker容器中运行GUI应用程序吗?
  • 通过搜索找到的图形访问的其他有用方法:Docker x11
  • 如果您在Docker容器中运行sshd,那么您就做错了!


注意:这个答案促进了我写的一个工具。

我已经创建了一个容器化的ssh服务器,您可以"坚持"到任何正在运行的容器。这样,您就可以用每个容器创建组合。唯一的要求是容器具有bash。

下面的示例将启动一个连接到名为"my container"的容器的ssh服务器。

1
2
3
4
5
6
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/jeroenpeters/docker-ssh


如果您在这里寻找一个Docker,像我一样撰写特定的答案,它提供了一种不必查找生成的容器ID的简单方法。

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

因此,要为"web"服务获取bash shell,可以执行以下操作:

1
$ docker-compose exec web bash

使用以下命令将ssh导入Docker容器:

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

如果您在Windows上使用Docker,并且想要让shell访问容器,请使用以下命令:

1
winpty docker exec -it <container_id> sh

很可能,您已经安装了Git-Bash。如果没有,请确保安装它。


在某些情况下,您的图像可以基于阿尔卑斯山。在这种情况下,它将抛出:

OCI runtime exec failed: exec failed: container_linux.go:348: starting
container process caused"exec: \"bash\": executable file not found in
$PATH": unknown

因为/bin/bash不存在。您应该使用以下方法代替:

1
docker exec -it 9f7d99aa6625 ash

1
docker exec -it 9f7d99aa6625 sh

要连接到Windows容器中的cmd,请使用

1
docker exec -it d8c25fde2769 cmd

其中,D8C25FDE2769是容器ID。


如果容器已经退出(可能是由于某些错误),您可以这样做

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

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

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

创建一个新的容器并将外壳放入其中。因为您指定了--rm,所以当您退出shell时,容器将被删除。


很简单!

列出你所有的码头工人图片:

1
sudo docker images

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

1
2
3
4
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

我的电脑上有两个Docker图像。假设我想运行第一个。

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

这将为您提供集装箱的终端控制。现在,您可以在容器内执行所有类型的shell操作。像执行ls一样,它将输出文件系统根目录中的所有文件夹。

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

Goinside溶液

安装goinside命令行工具:

1
sudo npm install -g goinside

进入码头集装箱内,集装箱的码头尺寸应符合以下要求:

1
goinside docker_container_name

旧答案

我们在~/.profile中放入了这段代码:

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

这不仅使每个人都能进入一个正在运行的容器中:

1
goinside containername

它还解决了固定码头集装箱码头尺寸的长期问题。如果你面对它的话,这是很烦人的。

另外,如果您遵循链接,您也将完成对Docker容器名称的命令。


使用此命令:

1
docker exec -it containerid /bin/bash

docker exec无疑是一个解决方案。处理您提出的问题的一个简单方法是将docker中的目录安装到本地系统的目录中。

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

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


用途:

1
docker attach <container name/id here>

另一种方法,尽管存在危险,但是使用attach,但是如果您使用ctrl+c退出会话,您也将停止容器。如果你只是想看看发生了什么,使用docker logs -f

1
2
3
4
5
6
7
8
9
10
:~$ 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)


要检查文件,请运行docker run -it /bin/bash以获得交互式终端。图像列表可以通过docker images获得。与docker exec相反,此解决方案也适用于图像未启动(或运行后立即退出)的情况。


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

您也可以在这个GUI中看到容器日志和大量容器信息(在设置选项卡中)。

Select Kitematic from menu

Click on exec


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

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

-T代表终端-我代表互动


在我的例子中,出于某种原因,我需要检查每个容器中涉及的所有网络信息。因此,以下命令必须在容器中有效…

1
2
3
4
5
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


如果您使用docker compose,那么这将带您进入docker容器。

1
docker-compose run container_name /bin/bash

在容器中,它将带您到dockerfile中定义的workdir。您可以通过以下方式更改您的工作目录:

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

docker exec -it /bin/bash

或者取决于外壳

docker exec -it /bin/sh

您可以通过docker ps命令获取容器ID

-i=交互式

-t=分配一个psuedo tty


另一种选择是使用nsenter。

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


对于docker compose up(docker4drupal)

1
docker-compose exec php bash

我在Linux笔记本电脑上使用Docker作为Drupal。在运行容器之后,我使用"EDOCX1"(10)来连接容器,这样我就可以运行drush命令。对我来说很好。