【问题标题】:How do I get into a Docker container's shell?如何进入 Docker 容器的外壳?
【发布时间】:2015-07-22 05:58:13
【问题描述】:

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

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

【问题讨论】:

  • 所以听起来答案是 docker attach。但是我怎样才能从 docker-compose 获得呢?
  • 使用 docker exec askubuntu.com/a/543057/35816 。使用docker ps获取容器id
  • sudo docker run -it --entrypoint /bin/bash <container_name> 让您以交互方式进入容器。然后可以使用cd <path> 检查容器中的文件系统
  • @Sergei 不正确, docker run 采用图像名称,而不是容器 ID。很长一段时间我都对运行容器感到困惑,这就是为什么我最终写了blog.andrewray.me/towards-a-strong-mental-model-of-docker
  • 1.列出你的容器:docker ps -a; 2. sudo docker start <container_name> 如果您已经有一个容器正在运行。更多参数见container start。 3.然后使用exec命令。

标签: docker docker-container


【解决方案1】:

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

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

docker exec -it <mycontainer> bash

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

上述命令中&lt;mycontainer&gt;是目标容器的名称或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

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

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

【讨论】:

  • 另外,docker exec 仅适用于正在运行的容器(否则使用 docker run -it --entrypoint /bin/bash 或类似名称)。
  • 为方便起见,-it-i-t 的组合,即--interactive(“即使未连接也保持STDIN 打开”)分别为--tty(“分配一个伪 TTY")。
  • 在基于 Alpine Linux 的容器上,您可能没有 bash,所以如果有,请改用 sh。
  • @L0j1k 是docker run -it --entrypoint /bin/bash &lt;imageid&gt; --any --more --args,只是为了澄清一下
  • @AlexanderMills 是的,为了进一步澄清,您拥有的那些 --any --more --args 将被输入到图像定义为 CMD 而不是 Docker 的任何位置(或者如果您的图像仅定义了 @987654343 @ 而不是CMD,那么这些选项将被输入到/bin/bash,正如您在此处指定的那样)。因此,例如任何其他docker run 选项(例如--net "host")都需要在&lt;imageid&gt; 之前。
【解决方案2】:

要 bash 进入正在运行的容器,请输入:

docker exec -t -i container_name /bin/bash

docker exec -ti container_name /bin/bash

docker exec -ti container_name sh

【讨论】:

  • 假设它是一个 Linux 容器?
  • /bin/bash 不是必需的,只是 bash 为我做的
  • 我更喜欢docker exec -it 而不是docker exec -t -i
  • 有没有办法指定用户?
  • @nakamin 根据文档,添加 -u 或 --user 标志将允许您指定用户。 docs.docker.com/engine/reference/commandline/exec
【解决方案3】:

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

正如其他答案所表明的那样,在本地可访问的运行容器中执行预安装的命令(包括 shell)并与之交互是很常见的,使用docker exec而不是 SSH

docker exec -it (container) (command)

注意:以下答案基于 Ubuntu(2016 年)。非 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($2,6)}' ## Display IP address (optional)

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

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

以下是一些相关资源:

【讨论】:

【解决方案4】:

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

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

因此,要为您的“网络”服务获取 Bash shell,您可以这样做:

$ docker-compose exec web bash

【讨论】:

  • 如果您的容器尚不存在,docker-compose run 也可以。
【解决方案5】:

注意:此答案宣传我编写的工具。

我创建了一个容器化的 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

【讨论】:

  • 这很甜蜜。这样做的最大好处是你得到了一个功能齐全的终端。当我使用“docker exec”方法时,我无法清除终端内容,less 每次运行时都会显示警告等。到目前为止,使用 Jeroen 的容器给了我更好的体验。只需确保查看文档。响应中的示例命令似乎不再有效。
  • 这是一个很棒的工具。你知道我如何将它用作詹金斯管道码头代理吗?我希望 jenkins 通过 SCP 将一些文件传输到远程主机并使用 SSH 执行它们
  • Docker 在 Windows 上: docker run -d -p 2222:22 -v //var/run/docker.sock:/var/run/docker.sock -e CONTAINER=my-container -e AUTH_MECHANISM=noAuth --name 节点管理器 jeroenpeeters/docker-ssh
【解决方案6】:

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

$ 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,因此当您退出 shell 时,容器将被删除。

【讨论】:

    【解决方案7】:

    使用以下命令启动与 Docker 容器的会话:

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

    【讨论】:

    • 或更短一点:sudo docker exec -it &lt;container ID&gt; bash
    【解决方案8】:

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

    winpty docker exec -it <container_id> sh
    

    很可能,您已经安装了Git Bash如果不安装,请务必安装它。

    【讨论】:

    • 假定一个 Linux Docker 容器?
    【解决方案9】:

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

    OCI 运行时执行失败:执行失败:container_linux.go:348:正在启动 容器进程导致“exec:\"bash\": executable file not found in $PATH": 未知

    因为/bin/bash 不存在。而不是这个,你应该使用:

    docker exec -it 9f7d99aa6625 ash
    

    docker exec -it 9f7d99aa6625 sh
    

    【讨论】:

      【解决方案10】:

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

      docker exec -it d8c25fde2769 cmd
      

      其中 d8c25fde2769 是容器 ID。

      【讨论】:

        【解决方案11】:

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

        【讨论】:

        • 假设一个 Linux Docker 镜像?
        【解决方案12】:

        GOINSIDE 解决方案

        安装goinside 命令行工具:

        sudo npm install -g goinside
        

        然后进入具有适当终端大小的 docker 容器:

        goinside docker_container_name
        

        旧答案

        我们已将此 sn-p 放入 ~/.profile:

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

        这不仅使每个人都能够通过以下方式进入正在运行的容器:

        goinside containername
        

        它还解决了一个长寿的problem about fixed Docker container terminal sizes。如果你面对它,这会很烦人。

        此外,如果您关注 the link,您的 docker 容器名称也将完成命令。

        【讨论】:

        • 谢谢。它就像一个魅力,至少对于那些已经包含 bash 的图像。可能不适用于基于 alpine 的图像,但是,可以使用专门为 sh/ash 等编写的不同函数来修复。
        【解决方案13】:

        很简单

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

        【讨论】:

          【解决方案14】:

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

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

          docker exec -it [container_id] /bin/bash
          

          你会写:

          dbash [container_id]
          

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

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

          【讨论】:

            【解决方案15】:
            $ docker exec -it <Container-Id> /bin/bash
            

            或者取决于shell,它可以是

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

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

            -i = 互动

            -t = 分配一个伪 TTY

            【讨论】:

              【解决方案16】:

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

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

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

              【讨论】:

                【解决方案17】:

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

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

                • 示例开始:docker exec -it &lt;containername&gt; /bin/bash
                • 退出:输入exit
                • 专业版:适用于所有容器(不依赖于 CMD/Entrypoint)
                • Contra:使用自己的会话和自己的环境变量创建一个新进程

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

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

                我们发现选项 2 更有用。例如,我们将apache2-foreground 更改为普通背景apache2 并在此之后启动bash

                【讨论】:

                  【解决方案18】:

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

                  这样你可以即时查看本地路径的变化。

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

                  【讨论】:

                  • 您的命令实际上是将主机的目录挂载到容器中。
                  • 是的!将备份备份到另一个目录,然后挂载卷,然后将备份移动到挂载的文件夹。
                  【解决方案19】:

                  用途:

                  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)
                  

                  【讨论】:

                    【解决方案20】:

                    使用这个命令:

                    docker exec -it containerid /bin/bash
                    

                    【讨论】:

                      【解决方案21】:

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

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

                      【讨论】:

                        【解决方案22】:

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

                        如果容器有bashshell

                        docker exec -it test /bin/bash
                        

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

                        docker run -it test /bin/sh
                        

                        【讨论】:

                          【解决方案23】:

                          就我而言,出于某种原因,我需要检查每个容器中涉及的所有网络信息。所以下面的命令在容器中一定是有效的...

                          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

                          【讨论】:

                            【解决方案24】:

                            另一种选择是使用nsenter

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

                            【讨论】:

                            • nsenter 存在许多问题。首先是它要求您对 docker 主机具有物理访问权限,这不是给定的(您可能正在使用远程 docker API)。此外,在nsenter 下运行可以使您免受 Docker 实施的一些安全和资源限制(根据您的环境,这可能是优点也可能是缺点)。
                            • 这几天连nsenter的作者says都用docker exec了。
                            • @larsks 是的,两者都有自己的好处。例如,this one 是 nsenter 优于 docker exec 的优势。 docker exec 在我看来更优雅。
                            • @L0j1k 为了避免混淆:您提到的帖子不是 nsenter 的作者,而是运行 nsenter 的 Docker 映像的作者。
                            【解决方案25】:

                            如果您使用的是 Docker Compose,那么这会将您带到 Docker 容器中。

                            docker-compose run container_name /bin/bash
                            

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

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

                            【讨论】:

                              【解决方案26】:

                              有两个选项我们可以使用shellbash这些方法直接连接到docker终端,但通常不支持bash,默认支持终端 要 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

                              【讨论】:

                                【解决方案27】:

                                对于 docker-compose up (Docker4Drupal)

                                docker-compose exec php bash
                                

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

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2020-02-06
                                  • 1970-01-01
                                  • 2020-03-24
                                  • 1970-01-01
                                  • 2019-04-09
                                  • 2018-04-19
                                  相关资源
                                  最近更新 更多