如何使用docker exec在Docker容器中运行命令
简介
Docker是一种容器化工具,帮助开发者创建和管理可移植的、一致的Linux容器。
在开发或部署容器时,你经常需要查看正在运行的容器内部,以检查其当前状态或调试一个问题。为此,Docker提供了docker exec
命令,在已经运行的容器中运行程序。
在本教程中,我们将了解docker exec
命令,以及如何使用它来运行命令,并在运行中的Docker容器中获得一个交互式外壳。
前提条件
本教程假设你已经安装了Docker,并且你的用户有权限运行docker
。如果你需要以根用户身份运行docker
,请记得在本教程中的命令前加上sudo
。
关于在没有sudo
的情况下使用Docker的更多信息,请参见我们的《如何安装Docker》教程中的《不使用Sudo执行Docker命令》一节。
启动一个测试容器
要使用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.log
。date
打印当前的日期和时间,像这样。
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容器中运行一个交互式外壳
如果你需要在Docker容器中启动一个交互式外壳,也许是为了探索文件系统或调试运行中的进程,可以使用docker exec
,并加上-i
和-t
标志。
-i
标志保持对容器的输入开放,而-t
标志创建一个伪终端,让shell可以附着在上面。这些标志可以像这样组合。
docker exec -it container-name sh
这将在指定的容器中运行sh
shell,给你一个基本的 shell 提示。要退出容器,请输入exit
然后按ENTER
。
exit
如果你的容器镜像包括一个更高级的shell,如bash
,你可以用上面的bash
替换sh
。
在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容器打开一个交互式外壳相同(如上一步中的 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
这将使用访客用户在容器中运行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。
推荐阅读