简介

Docker是一个容器化工具,可帮助开发人员创建和管理可移植、一致的 Linux 容器。

在开发或部署容器时,您通常需要查看正在运行的容器内部以检查其当前状态或调试问题。为此,Docker 提供了docker exec命令来在已经运行的容器中运行程序。

在本教程中,我们将了解docker exec命令以及如何使用它来运行命令并在正在运行的 Docker 容器中获取交互式 shell。

先决条件

本教程假设您已经安装了 Docker,并且您的用户有权运行docker。如果您需要以 root 用户身份运行docker,请记住在本教程中的命令前添加sudo

有关在没有sudo访问权限的情况下使用 Docker 的更多信息,请参阅我们的_如何安装 Docker_ 教程的Executing the Docker Command without Sudo部分。

启动测试容器

要使用docker exec命令,您需要一个正在运行的 Docker 容器。如果您还没有容器,请使用以下docker run命令启动测试容器:

docker run -d --name container-name alpine watch "date >> /var/log/date.log"

该命令从官方alpine镜像创建一个新的 Docker 容器。这是一个流行的 Linux 容器映像,它使用Alpine Linux,这是一个轻量级、最小的 Linux 发行版。

我们使用-d标志将容器与终端分离并在后台运行它。--name container-name将容器命名为container-name。您可以在此处选择您喜欢的任何名称,或者完全不使用它,让 Docker 自动为新容器生成一个唯一名称。

接下来我们有alpine,它指定了我们要用于容器的图像。

最后我们有watch "date >> /var/log/date.log"。这是我们要在容器中运行的命令。watch将重复运行你给它的命令,默认每两秒一次。在这种情况下watch将运行的命令是date >> /var/log/date.logdate打印当前日期和时间,如下所示:

OutputFri Jul 23 14:57:05 UTC 2021

该命令的>> /var/log/date.log部分重定向date的输出并将其附加到文件/var/log/date.log中。每两秒钟将在文件中附加一个新行,几秒钟后它将如下所示:

OutputFri Jul 23 15:00:26 UTC 2021
Fri Jul 23 15:00:28 UTC 2021
Fri Jul 23 15:00:30 UTC 2021
Fri Jul 23 15:00:32 UTC 2021
Fri Jul 23 15:00:34 UTC 2021

在下一步中,我们将学习如何查找 Docker 容器的名称。如果您已经有一个目标容器,但您不确定它的名称是什么,这将非常有用。

查找 Docker 容器的名称

我们需要向docker exec提供我们要使用的容器的名称(或容器 ID)。我们可以使用docker ps命令找到此信息:

docker ps

此命令列出服务器上运行的所有 Docker 容器,并提供有关它们的一些高级信息:

OutputCONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
76aded7112d4   alpine    "watch 'date >> /var…"   11 seconds ago   Up 10 seconds             container-name

在此示例中,容器 ID 和名称被突出显示。您可以使用任何一个来告诉docker exec使用哪个容器。

如果您想重命名容器,请使用docker rename命令:

docker rename container-name new-name

接下来,我们将运行几个使用docker exec在正在运行的 Docker 容器中执行命令的示例。

在 Docker 容器中运行交互式 Shell

如果您需要在 Docker 容器中启动交互式 shell,可能是为了探索文件系统或调试正在运行的进程,请使用docker exec-i-t标志。

-i标志保持对容器的输入打开,而-t标志创建一个 shell 可以附加到的伪终端。这些标志可以像这样组合:

docker exec -it container-name sh

这将在指定容器中运行shshell,为您提供基本的 shell 提示。要退出容器,请输入exit,然后按ENTER:

exit

如果您的容器映像包含更高级的 shell,例如bash,您可以将sh替换为上面的bash

在 Docker 容器中运行非交互式命令

如果您需要在正在运行的 Docker 容器中运行命令,但不需要任何交互性,请使用不带任何标志的docker exec命令:

docker exec container-name tail /var/log/date.log

该命令将在container-name容器上运行tail /var/log/date.log,并输出结果。默认情况下,tail命令将打印出文件的最后十行。如果您正在运行我们在第一部分中设置的演示容器,您将看到如下内容:

OutputMon Jul 26 14:39:33 UTC 2021
Mon Jul 26 14:39:35 UTC 2021
Mon Jul 26 14:39:37 UTC 2021
Mon Jul 26 14:39:39 UTC 2021
Mon Jul 26 14:39:41 UTC 2021
Mon Jul 26 14:39:43 UTC 2021
Mon Jul 26 14:39:45 UTC 2021
Mon Jul 26 14:39:47 UTC 2021
Mon Jul 26 14:39:49 UTC 2021
Mon Jul 26 14:39:51 UTC 2021

这本质上与为 Docker 容器打开一个交互式 shell(如上一步中使用docker exec -it container-name sh所做的那样)然后运行tail /var/log/date.log命令相同。但是,该命令不是打开 shell,运行命令,然后关闭 shell,而是在单个命令中返回相同的输出,而不打开伪终端。

在 Docker 容器的备用目录中运行命令

要在容器的某个目录中运行命令,请使用--workdir标志来指定目录:

docker exec --workdir /tmp container-name pwd

此示例命令将/tmp目录设置为工作目录,然后运行pwd命令,打印出当前工作目录:

Output/tmp

pwd命令已确认工作目录为/tmp

在 Docker 容器中以不同用户身份运行命令

要在容器内以其他用户身份运行命令,请添加--user标志:

docker exec --user guest container-name whoami

这将使用 guest 用户在容器中运行whoami命令。whoami命令打印出当前用户的用户名:

Outputguest

whoami命令确认容器的当前用户是guest

将环境变量传递到 Docker 容器中

有时您需要将环境变量与要运行的命令一起传递到容器中。-e标志允许您指定环境变量:

docker exec -e TEST=sammy container-name env

此命令将TEST环境变量设置为等于sammy,然后在容器内运行env命令。然后env命令打印出所有环境变量:

OutputPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=sammy
HOME=/root

TEST变量设置为sammy

要设置多个变量,请为每个变量重复-e标志:

docker exec -e TEST=sammy -e ENVIRONMENT=prod container-name env

如果你想传入一个充满环境变量的文件,你可以使用--env-file标志来实现。

首先,使用文本编辑器制作文件。我们将在此处打开一个带有nano的新文件,但您可以使用任何您喜欢的编辑器:

nano .env

我们使用.env作为文件名,因为这是使用这些类型的文件来管理版本控制之外的信息的流行标准。

KEY=value个变量写入文件,每行一个,如下所示:

.env

TEST=sammy
ENVIRONMENT=prod

保存并关闭文件。要保存文件并退出nano,请按CTRL+O,然后按ENTER保存,然后按CTRL+X退出。

现在运行docker exec命令,在--env-file之后指定正确的文件名:

docker exec --env-file .env container-name env

OutputPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=sammy
ENVIRONMENT=prod
HOME=/root

设置文件中的两个变量。

您可以使用多个--env-file标志指定多个文件。如果文件中的变量相互重叠,则命令中最后列出的文件将覆盖以前的文件。

常见错误

使用docker exec命令时,可能会遇到几个常见错误:

Error: No such container: container-name

No such container错误表示指定的容器不存在,可能表示容器名称拼写错误。使用docker ps列出正在运行的容器并仔细检查名称。

Error response from daemon: Container 2a94aae70ea5dc92a12e30b13d0613dd6ca5919174d73e62e29cb0f79db6e4ab is not running

这个not running消息意味着容器存在,但是它被停止了。可以用docker start container-name启动容器

Error response from daemon: Container container-name is paused, unpause the container before exec

Container is paused错误很好地解释了这个问题。在继续之前,您需要使用docker unpause container-name取消暂停容器。

结论

在本教程中,我们学习了如何在正在运行的 Docker 容器中执行命令,以及执行此操作时可用的一些命令行选项。

有关 Docker 的更多信息,请参阅我们的Docker 标签页面,其中包含指向 Docker 教程、Docker 相关问答页面等的链接。

如需安装 Docker 的帮助,请查看如何在 Ubuntu 20.04上安装和使用 Docker。

Logo

开发云社区提供前沿行业资讯和优质的学习知识,同时提供优质稳定、价格优惠的云主机、数据库、网络、云储存等云服务产品

更多推荐