如何使用 docker container run 命令管理容器

DockerDockerBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,你将通过实践掌握使用 docker container run 命令高效管理容器的技巧。你将学习如何在后台运行容器(detached 模式),并为容器分配自定义名称以便于识别。

此外,你还将探索以下核心技能:在保持 STDIN 开启状态下附加到运行中的容器、将容器端口发布到宿主机实现外部访问、挂载数据卷确保数据持久化,以及通过设置环境变量和添加主机条目来配置容器。这些基础技能对于构建和管理 Docker 化应用至关重要。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/VolumeOperationsGroup(["Volume Operations"]) docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/ps("List Running Containers") docker/ContainerOperationsGroup -.-> docker/stop("Stop Container") docker/ContainerOperationsGroup -.-> docker/rm("Remove Container") docker/ContainerOperationsGroup -.-> docker/attach("Attach to Container") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/VolumeOperationsGroup -.-> docker/volume("Manage Volumes") subgraph Lab Skills docker/run -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} docker/ps -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} docker/stop -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} docker/rm -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} docker/attach -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} docker/exec -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} docker/pull -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} docker/volume -.-> lab-555121{{"如何使用 docker container run 命令管理容器"}} end

以分离模式运行容器并指定名称

在本步骤中,你将学习如何以分离模式(detached mode)运行 Docker 容器,并为其指定自定义名称。以分离模式运行容器意味着容器将在后台运行,你不会直接在终端看到其输出。为容器命名可以方便后续识别和管理。

首先,让我们拉取 hello-world 镜像。这是一个非常小的镜像,常用于测试 Docker 是否正常工作。

docker pull hello-world

你将看到镜像正在被拉取的输出信息,随后会出现拉取成功的确认消息。

现在,让我们以分离模式运行 hello-world 容器。我们将使用 -d 参数表示分离模式,并用 --name 参数指定容器名称。我们将这个容器命名为 my-hello-world

docker run -d --name my-hello-world hello-world

执行此命令后,Docker 会打印一长串字符,这是容器的 ID。这表示容器已在后台启动。

要验证容器是否正在运行,可以使用 docker ps 命令。该命令会列出所有当前运行的容器。

docker ps

你应该能看到正在运行的容器列表,其中应该包含名为 my-hello-world 的容器。STATUS 列会显示该容器已于几秒前退出。hello-world 容器的设计就是短暂运行、打印消息后退出。即使它已退出,仍会被 docker ps 列出,因为它是以分离模式运行的。

要查看所有容器(包括已退出的),可以使用 docker ps -a 命令。

docker ps -a

这将显示包含 my-hello-world 的列表及其状态(Exited)。

附加到运行中的容器并保持 STDIN 开启

在本步骤中,你将学习如何附加到运行中的容器并保持标准输入(STDIN)开启。这对于需要与运行交互式进程(如 shell)的容器进行交互特别有用。

在前一步骤中,我们运行的 hello-world 容器会立即退出。为了演示附加操作,我们需要一个持续运行的容器。一个简单的方法是运行一个包含交互式 shell 的容器。

首先拉取 ubuntu 镜像,这是许多应用程序常用的基础镜像:

docker pull ubuntu

现在,我们将以分离模式(-d)运行一个 ubuntu 容器,分配伪终端(-t),并保持 STDIN 开启(-i)。我们将其命名为 my-ubuntu,并在容器内运行 /bin/bash(Bash shell 的路径):

docker run -itd --name my-ubuntu ubuntu /bin/bash

-i 参数保持 STDIN 开启,允许你向容器发送输入;-t 参数分配伪终端,这是交互式 shell 会话必需的;-d 参数让容器在后台运行。

执行后终端会打印容器 ID,表示容器已在后台运行。

现在使用 docker attach 命令附加到正在运行的 my-ubuntu 容器:

docker attach my-ubuntu

执行后你将看到 Ubuntu 容器内的 Bash shell 提示符。此时你已连接到容器的标准输入、输出和错误流。

现在可以与容器 shell 交互了。例如运行 ls 命令查看容器当前目录的文件:

ls

你将看到 Ubuntu 容器根目录(/)的内容。

若要从容器分离而不停止它,需使用特定按键组合:先按 CTRL+p 再按 CTRL+q。现在尝试这个组合键。

你会返回到宿主机的终端提示符,而容器仍在后台运行。可通过 docker ps 验证:

docker ps

应该能看到 my-ubuntu 列为运行中的容器。

注意:如果附加时直接按 CTRL+c,会向容器内进程(Bash shell)发送信号,可能导致容器停止。使用 CTRL+pCTRL+q 才是标准的分离不停止容器的方式。

将容器端口发布到宿主机

在本步骤中,你将学习如何将 Docker 容器的端口发布到宿主机。这样你就可以通过宿主机的网络访问容器内运行的服务。

首先,让我们停止并移除上一步骤中的 my-ubuntu 容器以避免冲突:

docker stop my-ubuntu
docker rm my-ubuntu

执行每条命令后都会打印容器名称,确认容器已停止并被移除。

现在,我们将在容器内运行一个简单的 Web 服务器,并将其端口发布到宿主机。我们将使用流行的 Web 服务器镜像 nginx

拉取 nginx 镜像:

docker pull nginx

接下来,我们以分离模式(-d)运行 nginx 容器,并将容器内的 80 端口发布到宿主机的 8080 端口。使用 -p 参数进行端口发布,格式为 宿主机端口:容器端口。同时为容器命名为 my-nginx

docker run -d --name my-nginx -p 8080:80 nginx

-p 8080:80 这部分将容器内的 80 端口(Nginx 默认监听端口)映射到宿主机的 8080 端口。

执行后会打印容器 ID,表示容器已在后台运行。

要验证端口发布是否正确以及 Web 服务器是否可访问,可以在宿主机上使用 curl 命令访问 8080 端口的 localhost

curl http://localhost:8080

终端输出中应该会显示 Nginx 的默认欢迎 HTML 页面。这确认了你可以通过宿主机的 8080 端口访问容器内运行的 Nginx Web 服务器。

你也可以使用 docker ps 查看运行中的容器及其发布的端口:

docker ps

输出中应该会列出 my-nginx,在 PORTS 列中会显示 0.0.0.0:8080->80/tcp,表示容器内的 80 端口已映射到宿主机所有网络接口的 8080 端口。

挂载数据卷实现持久化存储

在本步骤中,你将学习如何使用 Docker 数据卷来持久化容器生成和使用的数据。默认情况下,容器内的数据是临时的,当容器被删除时数据也会丢失。数据卷提供了一种将数据存储在容器文件系统之外的方式,使得数据在容器停止或删除后依然能够保留。

首先,让我们停止并移除上一步骤中的 my-nginx 容器:

docker stop my-nginx
docker rm my-nginx

现在,我们将创建一个 Docker 数据卷。数据卷由 Docker 管理,存储在宿主机上的专用区域:

docker volume create my-volume

执行后会显示数据卷名称(my-volume),确认已成功创建。

你可以使用 docker volume ls 命令查看现有数据卷:

docker volume ls

在数据卷列表中应该能看到 my-volume

接下来,我们将运行一个新的 nginx 容器,并将 my-volume 挂载到容器内的 Nginx 默认网站根目录 /usr/share/nginx/html。这意味着容器内该目录下的所有文件实际上都存储在宿主机的 my-volume 中。

我们以分离模式(-d)运行容器,将容器内的 80 端口发布到宿主机的 8081 端口(-p 8081:80),命名为 my-nginx-volume,并使用 -v 参数挂载数据卷。命名数据卷的挂载格式为 数据卷名称:容器内路径

docker run -d --name my-nginx-volume -p 8081:80 -v my-volume:/usr/share/nginx/html nginx

执行后会显示容器 ID,表示容器正在运行。

现在,让我们在挂载的数据卷中放置一个简单的 HTML 文件。可以通过 docker exec 在运行中的容器内执行命令来实现。我们将在 /usr/share/nginx/html 目录下创建名为 index.html 的文件:

docker exec my-nginx-volume sh -c 'echo "<h1>Hello from the volume!</h1>" > /usr/share/nginx/html/index.html'

该命令在 my-nginx-volume 容器内执行 shell(sh -c),并通过 echo 命令创建 index.html 文件。

现在,我们访问宿主机 8081 端口的 Web 服务,查看刚创建的 index.html 文件内容:

curl http://localhost:8081

输出中应该会显示 <h1>Hello from the volume!</h1>。这确认了我们创建的文件正由 Nginx 提供服务,且由于文件被写入挂载的数据卷,数据已被持久化存储。

为了演示持久化效果,让我们停止并移除 my-nginx-volume 容器:

docker stop my-nginx-volume
docker rm my-nginx-volume

现在,我们运行一个容器,挂载相同的数据卷。将新容器命名为 my-nginx-volume-new,并将其 80 端口发布到宿主机的 8082 端口:

docker run -d --name my-nginx-volume-new -p 8082:80 -v my-volume:/usr/share/nginx/html nginx

新容器正在运行,并且使用了相同的 my-volume。让我们访问 8082 端口的 Web 服务:

curl http://localhost:8082

输出中仍然会显示 <h1>Hello from the volume!</h1>。这是因为 index.html 文件存储在 my-volume 中,即使原始容器被删除后数据依然保留。新容器通过挂载相同的数据卷,能够访问之前写入的数据。

这充分展示了数据卷在独立于容器生命周期持久化数据方面的强大能力。

设置环境变量与添加主机条目

在本步骤中,你将学习如何为 Docker 容器设置环境变量,以及如何向容器的 /etc/hosts 文件添加自定义条目。环境变量是配置容器内运行应用程序的常用方式,而添加主机条目则有助于服务发现或覆盖容器内的 DNS 解析。

首先,让我们停止并移除上一步骤中的 my-nginx-volume-new 容器:

docker stop my-nginx-volume-new
docker rm my-nginx-volume-new

现在,我们将运行一个简单容器并设置环境变量。再次使用 ubuntu 镜像,执行打印环境变量值的命令。我们将设置名为 MY_VARIABLE 的环境变量,其值为 hello_docker。使用 -e 参数设置环境变量,格式为 变量名=值

docker run --rm -e MY_VARIABLE=hello_docker ubuntu env | grep MY_VARIABLE

该命令包含以下要素:

  • --rm 在容器退出后自动删除容器
  • -e MY_VARIABLE=hello_docker 在容器内设置环境变量
  • ubuntu 为使用的镜像
  • env 是容器内执行的打印所有环境变量的命令
  • | grep MY_VARIABLE 过滤输出仅显示包含 MY_VARIABLE 的行

终端输出中应该会显示 MY_VARIABLE=hello_docker,确认环境变量已在容器内成功设置。

接下来,学习如何向容器的 /etc/hosts 文件添加自定义主机条目。当需要让容器将特定主机名解析到指定 IP 地址(不依赖外部 DNS)时,这个功能非常有用。我们使用 --add-host 参数实现,格式为 主机名:IP地址

我们将运行另一个 ubuntu 容器,添加将主机名 my-service 映射到 IP 地址 192.168.1.100 的条目,然后使用 cat 命令查看容器内 /etc/hosts 文件内容,并用 grep 检查添加的条目:

docker run --rm --add-host my-service:192.168.1.100 ubuntu cat /etc/hosts | grep my-service

该命令包含以下要素:

  • --rm 在容器退出后删除容器
  • --add-host my-service:192.168.1.100 向容器的 hosts 文件添加映射条目
  • ubuntu 为使用的镜像
  • cat /etc/hosts 是容器内执行的打印 hosts 文件的命令
  • | grep my-service 过滤输出查找包含 my-service 的行

终端输出中应该会显示类似 192.168.1.100 my-service 的内容,确认自定义主机条目已成功添加到容器的 hosts 文件。

如果需要,你可以在单个 docker run 命令中同时设置环境变量和添加主机条目。

总结

在本实验中,你学习了如何使用 docker run 命令管理容器。首先通过 -d 参数以分离模式运行容器,并使用 --name 参数为其指定自定义名称,然后通过 docker psdocker ps -a 验证容器状态。

随后你探索了以下操作:在保持 STDIN 打开的情况下附加到运行中的容器,使用 -p 参数将容器端口发布到主机以实现网络访问,通过 -v 参数挂载数据卷确保数据在容器生命周期结束后依然持久化,以及使用 -e 参数设置环境变量和 --add-host 参数添加主机条目来配置容器环境。