1. 概述

我们知道Docker是一个强大的工具,用于创建、部署和运行应用程序。

图像与容器教程中,我们讨论了Docker镜像如何使用层构建。我们也讨论了第一层通常是操作系统。

那么,是否有可能连接到容器的操作系统呢?答案是肯定的。现在我们将学习如何做到这一点。

2. 连接到现有容器

如果我们要连接到现有的容器,我们应该有一个处于运行状态的容器。为此,我们必须使用docker ps命令检查系统中的容器状态:

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                  PORTS               NAMES
4b9d83040f4a        hello-world         "/hello"            8 days ago          Exited (0) 8 days ago                       dazzling_perlman

因为我们没有正在运行的容器,让我们以RabbitMQ容器为例启动一个:

$ docker run -d rabbitmq:3

一旦容器启动,我们将在另一个docker ps调用中看到它:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                NAMES
b7a9f5eb6b85        rabbitmq:3          "docker-entrypoint.s…"   25 minutes ago      Up 25 minutes       4369/tcp, 5671-5672/tcp, 25672/tcp   trusting_bose

现在,连接到这个容器就像执行以下操作一样简单:

$ docker exec -it b7a9f5eb6b85 sh

到目前为止,我们已经在容器内部获得了交互式shell:

  • docker exec告诉Docker我们想要在运行的容器中执行命令
  • -it参数意味着将以交互模式执行 - 它保持STIN打开
  • b7a9f5eb6b85是容器ID
  • sh是我们想要执行的命令

让我们探索我们新创建的容器的操作系统:

$ cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

看来这是一个Bionic Beaver Ubuntu。如果我们检查RabbitMQ Dockerfile中的FROM指令,我们会发现这个镜像是使用Ubuntu 18.04构建的。

我们可以使用exit命令或仅通过CTRL+d断开与容器的连接。

这个示例很容易,因为当我们启动RabbitMQ容器时,它会一直运行直到我们停止它。另一方面,有时我们需要处理不会存活的容器,例如操作系统容器。让我们看看如何访问它们。

3. 在交互模式下运行容器

如果我们尝试启动一个新的操作系统容器,例如18.04 Ubuntu,我们会发现它不会保持运行:

$ docker run ubuntu:18.04
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                                NAMES
08c26636709f        ubuntu:18.04        "/bin/bash"              10 seconds ago      Exited (0) 7 seconds ago                                        heuristic_dubinsky
b7a9f5eb6b85        rabbitmq:3          "docker-entrypoint.s…"   About an hour ago   Up About an hour           4369/tcp, 5671-5672/tcp, 25672/tcp   trusting_bose

当RabbitMQ容器仍在运行时,Ubuntu容器已停止。因此,我们无法使用docker exec命令连接到此容器。

避免这种情况的一种方法是在交互模式下运行此容器:

$ docker run -it ubuntu:18.04

所以现在我们在容器内部,可以检查shell类型:

$ echo $0
/bin/bash

实际上,在交互模式下启动容器时使用--rm参数很有帮助。退出时它将确保删除容器:

$ docker run -it --rm ubuntu:18.04

4. 保持容器运行

有时我们会遇到一些奇怪的情况,需要启动并连接到容器,但交互模式不起作用。

如果遇到这种情况,可能是因为出了问题并且需要进行纠正。

但是,如果需要快速解决方法,我们可以在容器中运行tail命令:

$ docker run -d ubuntu:18.04 tail -f /dev/null

通过此命令,我们以脱机/后台模式(\-d)启动新的容器,并在容器内执行tail -f /dev/null命令。结果,这将迫使我们的容器永远运行。

现在我们只需要使用docker exec命令以我们之前看到的方式连接:

$ docker exec -it CONTAINER_ID sh

请记住,这是一种解决方法,仅在开发环境中使用。

5. 结论

在这个教程中,我们看到了如何连接到运行的容器的外壳,以及如何启动交互式容器。