如何进入 Docker 容器的 shell?

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

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

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

docker attach 会让您连接到 Docker 容器,但这与 ssh 并不是一回事。例如,如果您的容器是 运行 网络服务器,docker attach 可能会将您连接到网络服务器进程的 stdout。它不一定会给你 shell.

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

docker exec -it <mycontainer> bash

当然,无论您使用什么命令 运行ning 都必须存在于容器文件系统中。

上述命令中<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

我可以通过 运行ning 完成同样的事情:

$ docker exec -it d2d4a89aaee9 ip addr

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

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

另一种选择是使用 nsenter

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

docker exec 一定会解决的。解决您提出的问题的一种简单方法是 将 Docker 内的目录挂载到本地系统的目录 .

方便您即时查看本地路径的变化

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

注意:这个回答推广了我写的一个工具。

我创建了一个容器化的 SSH 服务器,您可以 'stick' 到任何 运行 容器。这样你就可以用每个容器创建组合。唯一的要求是容器有 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

要 bash 放入 运行 容器中,请键入:

docker exec -t -i container_name /bin/bash

docker exec -ti container_name /bin/bash

docker exec -ti container_name sh

使用此命令在 Docker 容器中启动会话:

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

历史记录:在我写这个答案的时候,问题的标题是:“How to ssh into a docker container?”

正如其他答案所证明的那样,使用 docker exec、[=30= 在 locally-accessible 运行ning 容器中执行预安装的命令(包括 shell)并与之交互是很常见的] 而不是 SSH:

docker exec -it (container) (command)

注意:以下答案基于 Ubuntu(2016 年)。 non-Debian 个容器需要对安装过程进行一些翻译。

比方说,出于您自己的原因,您确实想要使用 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(,6)}' ## Display IP address (optional)

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

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

以下是一些相关资源:

使用:

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)

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

winpty docker exec -it <container_id> sh

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

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

docker exec -it d8c25fde2769 cmd

其中d8c25fde2769是容器id。

对于docker-组成 (Docker4Drupal)

docker-compose exec php bash

我在 Linux 笔记本电脑上使用 Docker for Drupal。在 运行 连接容器后,我使用“docker-compose exec php bash”连接容器,这样我就可以 运行 突击突击队。它对我来说很好用。

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

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

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

因此,要为您的 'web' 服务获取 Bash shell,您可以:

$ docker-compose exec web bash

如果您正在使用 Docker Compose,那么这将带您进入 Docker 容器。

docker-compose run container_name /bin/bash

在容器内,它将带您到 Docker 文件中定义的 WORKDIR。您可以通过

更改您的工作目录
WORKDIR directory_path # E.g  /usr/src -> container's path

GOINSIDE 解决方案

安装 goinside 命令行工具:

sudo npm install -g goinside

然后进入具有适当终端尺寸的 docker 容器:

goinside docker_container_name

旧答案

我们已将此代码段放入 ~/.profile:

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

这不仅让每个人都可以进入 运行 容器:

goinside containername

它还解决了一个长期存在的问题。遇到了就很烦了

此外,如果您遵循 ,您的 docker 容器名称也会有命令完成。

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

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不存在。而不是这个你应该使用:

docker exec -it 9f7d99aa6625 ash

docker exec -it 9f7d99aa6625 sh

如果 Docker 安装了 Kitematic,则可以使用 GUI。从 Docker 图标和 Kitematic window select 容器中打开 Kitematic,然后单击 exec 图标。

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

很简单!

列出所有 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

我的电脑上有两张 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

使用这个命令:

docker exec -it containerid /bin/bash

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

ip
route
netstat
ps
...

我检查了所有这些答案,none对我很有帮助。我在其他网站上搜索过信息。我不会在这里添加超级link,因为它不是用英文写的。所以我只是把这个 post 和一个总结解决方案放在一起,供与我有相同要求的人使用。

假设您有一个 运行 名为 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 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

创建一个新容器并将 shell 放入其中。由于您指定了 --rm,因此当您退出 shell.

时容器将被删除
$ docker exec -it <Container-Id> /bin/bash

或者根据shell,可以是

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

您可以通过docker ps命令

获取container-Id

-i = 互动

-t = 分配伪 TTY

您可以通过传递选项 -ti

与 docker 容器中的终端进行交互
docker run --rm -ti <image-name>
eg: docker run --rm -ti ubuntu

-t代表终端 -i 代表交互式

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

所以结果是,而不是键入:

docker exec -it [container_id] /bin/bash

你会写:

dbash [container_id]

将以下内容放入您的 ~/.bash_profile(或任何适合您的内容),然后打开一个新终端 window 并享受快捷方式:

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

要执行到名为 test 的 运行 容器中,下面是以下命令

如果容器有bashshell

docker exec -it test /bin/bash

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

docker run -it test /bin/sh

根据目标至少有 2 个选项。

选项 1: 创建一个新的 bash 进程并加入其中 (更简单)

  • 样本开始:docker exec -it <containername> /bin/bash
  • 退出:输入exit
  • Pro:适用于所有容器(不依赖于 CMD/Entrypoint)
  • Contra:创建一个具有自己的会话和自己的环境变量的新进程

选项 2: 附加到已经 运行 bash (更好)

  • 样本开始:docker attach --detach-keys ctrl-d <containername>
  • 退出:使用键 ctrld
  • Pro:加入容器中完全相同的 运行 bash。您有相同的会话和相同的环境变量。
  • Contra:仅当 CMD/Entrypoint 是交互式 bash 时才有效,例如 CMD ["/bin/bash"]CMD ["/bin/bash", "--init-file", "myfile.sh"] AND 如果容器已从交互式选项开始,例如 docker run -itd <image> (-i=interactive, -t=tty and -d=deamon [opt])

我们发现选项 2 更有用。例如,我们将 apache2-foreground 更改为普通背景 apache2,然后开始 bash

有两个选项我们可以使用这些方法直接连接到docker终端 shellbash 但通常不支持 bash 并且默认支持 sh终端 要将 sh 放入 运行 容器,请键入:

docker exec -it container_name/container_ID sh

要 bash 放入 运行 容器中,请键入:

docker exec -it container_name/container_ID bash

并且你只想使用 bash 终端而不是你可以在你的 Dockerfile 中安装 bash 终端,例如 RUN apt install bash -y

docker exec -it <container_id or name> bash

docker exec -it <container_id or name> /bin/bash

2022 年解决方案

考虑另一个选择

为什么需要它?

有一堆现代 docker-images 基于 distroless 基础图像(它们也没有 /bin/bash /bin/sh) 所以不可能 docker exec -it {container-name} bash 进入它们。

如何shell-in任何容器

使用opener:

  • 需要在您的环境中 add alias opener wordpress
  • 随处可用docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock artemkaxboy/opener wordpress

您可以使用要连接的任何容器的名称或 ID 或 image-name 而不是 wordpress


工作原理

Opener 是一组 python 脚本 wrapped-up 到 docker 图像。它通过任何唯一属性(名称、ID、端口、图像)找到目标容器,尝试使用 bash 连接到目标。如果未找到 bash,opener 会尝试使用 sh 进行连接。最后,如果未找到 sh,opener 将 busybox 安装到目标容器并使用 busybox shell 连接到目标,opener 在断开连接期间删除 busybox