简介
Docker 容器已成为现代应用程序开发和部署的基本组成部分。在处理多个容器时,确保它们之间的正确连接对于应用程序的正常运行至关重要。
在本实验中,你将学习如何验证和排查 Docker 容器之间的连接问题。我们将从基本的 Docker 容器概念开始,设置用于测试的容器,然后探索各种方法来检查和诊断容器之间的网络连接。
在本教程结束时,你将能够自信地测试、验证和解决容器化应用程序中的连接问题。
本实验需要互联网连接才能进行学习,因此只有专业版用户才能启动虚拟机。将你的账户升级为专业版。
Docker 容器已成为现代应用程序开发和部署的基本组成部分。在处理多个容器时,确保它们之间的正确连接对于应用程序的正常运行至关重要。
在本实验中,你将学习如何验证和排查 Docker 容器之间的连接问题。我们将从基本的 Docker 容器概念开始,设置用于测试的容器,然后探索各种方法来检查和诊断容器之间的网络连接。
在本教程结束时,你将能够自信地测试、验证和解决容器化应用程序中的连接问题。
本实验需要互联网连接才能进行学习,因此只有专业版用户才能启动虚拟机。将你的账户升级为专业版。
在测试容器之间的连接之前,我们需要创建一些容器来进行操作。在这一步中,我们将设置两个简单的 Docker 容器,并了解基本的 Docker 命令。
Docker 容器是轻量级的独立软件包,其中包含运行应用程序所需的一切:代码、运行时环境、系统工具、库和设置。容器共享主机的操作系统内核,但在隔离的环境中运行。
让我们从基于 Ubuntu 镜像创建两个简单的容器开始。在整个实验中,我们将使用这些容器来测试它们之间的连接。
首先,创建我们的第一个容器:
docker run -d --name container1 ubuntu:22.04 sleep infinity
现在,创建第二个容器:
docker run -d --name container2 ubuntu:22.04 sleep infinity

命令参数解释:
-d:以分离模式(在后台)运行容器--name:为容器分配一个名称ubuntu:22.04:要使用的 Docker 镜像(Ubuntu 22.04 版本)sleep infinity:一个使容器无限期运行的命令要检查我们的容器是否正常运行,请使用以下命令:
docker ps
你应该会看到类似以下的输出:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f8d97c645cce ubuntu:22.04 "sleep infinity" 5 秒前 已启动 4 秒 container2
a2c516a57cb8 ubuntu:22.04 "sleep infinity" 18 秒前 已启动 17 秒 container1
如果你没有看到两个容器都列出,它们可能没有正确启动。你可以尝试再次创建它们。
默认情况下,Ubuntu 容器镜像非常精简,不包括我们需要的网络工具。让我们在两个容器中都安装这些工具:
对于容器 1:
docker exec container1 apt-get update
docker exec container1 apt-get install -y iputils-ping net-tools iproute2 curl
对于容器 2:
docker exec container2 apt-get update
docker exec container2 apt-get install -y iputils-ping net-tools iproute2 curl
这些命令:
docker exec 在正在运行的容器内运行命令apt-get update 更新软件包列表iputils-ping 用于 ping 命令,net-tools 用于 netstat 命令,iproute2 用于 IP 相关命令,以及 curl)现在我们的容器已准备好进行下一步的连接测试。
Docker 容器通过网络相互通信。了解 Docker 网络的工作原理对于测试和排查容器之间的连接问题至关重要。
安装 Docker 时,它会自动创建几个默认网络。最常用的有:
bridge:如果未指定网络,容器默认连接到此网络host:容器直接使用主机的网络(无隔离)none:容器无网络访问权限让我们检查一下系统上的网络:
docker network ls
你应该会看到类似以下的输出:
NETWORK ID NAME DRIVER SCOPE
1b95853bf83b bridge bridge local
91199fc6ad2e host host local
1078d2c781b6 none null local
默认情况下,我们的两个容器都连接到默认桥接网络。让我们检查一下这个网络:
docker network inspect bridge
此命令会显示桥接网络的详细信息,包括连接到它的容器及其 IP 地址。在输出中,查找“Containers”部分,以查看列出的 container1 和 container2 及其 IP 地址。
为了处理容器连接,我们需要知道分配给容器的 IP 地址。有几种方法可以获取此信息:
使用 docker inspect:
docker inspect --format='{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container1
或者在容器内部:
docker exec container1 hostname -i
记录两个容器的 IP 地址:
docker exec container1 hostname -i
docker exec container2 hostname -i
输出将显示每个容器的 IP 地址,在默认桥接网络上,该地址通常以 172.17.0.x 开头。
虽然默认桥接网络允许容器通信,但创建自定义网络可提供更好的隔离和内置 DNS 解析(容器可以通过名称而不是 IP 相互访问)。
让我们创建一个自定义桥接网络:
docker network create --driver bridge my-network
现在,让我们将现有的容器连接到这个新网络:
docker network connect my-network container1
docker network connect my-network container2
我们可以验证我们的容器已连接到新网络:
docker network inspect my-network
现在我们的容器已连接到默认桥接网络和我们的自定义 my-network。在下一步中,我们将测试它们之间的连接。
既然我们已经设置好容器并将它们连接到网络,就可以测试它们之间的连接了。我们将使用几种方法来验证容器之间是否能够相互通信。
测试基本网络连接的最简单方法是使用 ping 命令,该命令会向目标主机发送 ICMP 回显请求。
让我们使用 IP 地址从 container1 向 container2 发送 Ping 请求:
## 首先,获取 container2 的 IP 地址
CONTAINER2_IP=$(docker exec container2 hostname -i)
echo "Container2 IP: $CONTAINER2_IP"
## 获取 CONTAINER2_IP 的第一个 IP 地址
CONTAINER2_IP=$(echo $CONTAINER2_IP | cut -d' ' -f1)
echo "Container2 IP: $CONTAINER2_IP"
## 现在从 container1 向 container2 发送 Ping 请求
docker exec container1 ping -c 4 $CONTAINER2_IP
你应该会看到类似以下的输出:
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.095 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.067 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.087 ms
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.067/0.085/0.095/0.000 ms
自定义 Docker 网络的一个优点是它们提供自动 DNS 解析,允许容器通过名称相互访问。
让我们通过按名称 Ping 容器来测试 DNS 解析:
docker exec container1 ping -c 4 container2
这应该可行,因为两个容器都在我们的自定义 my-network 上,该网络提供 DNS 解析。你应该会看到与之前测试类似的 Ping 响应,但使用的是容器名称而不是 IP。
对于运行 Web 服务的应用程序,我们通常需要测试 HTTP 连接。让我们在 container2 中设置一个简单的 HTTP 服务器,并从 container1 测试与它的连接。
首先,在 container2 中启动一个基本的 HTTP 服务器:
docker exec container2 apt-get install -y python3
docker exec -d container2 bash -c "echo 'Hello from container2' > /index.html && cd / && python3 -m http.server 8080"
等待几秒钟让服务器启动,然后从 container1 测试连接:
docker exec container1 curl -s http://container2:8080
你应该会看到输出:
Hello from container2
这确认了 container1 可以使用容器名称进行 DNS 解析,从而连接到 container2 的 HTTP 服务。
了解如何使用其他工具测试连接也很有用。让我们尝试使用 nc(netcat)检查特定端口是否打开:
## 确保在 container1 中安装了 netcat
docker exec container1 apt-get install -y netcat
## 测试与 container2 上的 HTTP 服务器的连接
docker exec container1 nc -zv container2 8080
你应该会看到表明连接成功的输出:
Connection to container2 (172.18.0.3) 8080 port [tcp/*] succeeded!
这些测试确认了我们的容器在网络级别(Ping)和应用程序级别(HTTP)都可以相互通信。
如果你没有任何连接问题,可以跳过此步骤。
既然我们已经了解了如何测试容器之间的连接,那么让我们来探讨如何排查常见的连接问题。
在处理 Docker 容器网络时,你可能会遇到几个常见问题:
让我们针对这些潜在问题逐一进行排查步骤。
首先,让我们检查容器的网络配置:
## 查看 container1 的网络接口
docker exec container1 ip addr show
## 查看 container2 的网络接口
docker exec container2 ip addr show
输出显示了每个容器中的所有网络接口。每个连接的 Docker 网络都显示为一个带有分配的 IP 地址的 eth 接口。
让我们检查容器中的路由配置:
docker exec container1 route -n
这将显示 container1 的路由表,指示网络流量的导向位置。
要确定应用程序是否正在正确监听连接,请使用:
docker exec container2 netstat -tuln
这将显示所有 TCP 和 UDP 监听端口。我们的 HTTP 服务器应该在端口 8080 上监听。
为了进行更详细的网络流量分析,我们可以使用 tcpdump 来捕获和分析数据包:
## 在 container1 中安装 tcpdump
docker exec container1 apt-get install -y tcpdump dnsutils
## 捕获数据包 10 秒钟
docker exec container1 timeout 10 tcpdump -i eth0 -n
在运行此命令时,打开另一个终端并生成一些流量:
docker exec container1 ping -c 3 container2
你应该会在 tcpdump 输出中看到捕获的 ICMP 数据包。
如果你在容器之间的 DNS 解析方面遇到问题:
## 检查 DNS 配置
docker exec container1 cat /etc/resolv.conf
## 测试 DNS 解析
docker exec container1 nslookup container2
让我们通过暂时将 container1 与我们的自定义网络断开连接来模拟一个连接问题:
## 将 container1 从 my-network 断开连接
docker network disconnect my-network container1
## 尝试按名称 Ping(这应该会失败)
docker exec container1 ping -c 2 container2
你应该会看到 Ping 失败,因为在从共享网络断开连接后,container1 无法再通过名称解析 container2。
让我们重新连接它:
## 将 container1 重新连接到 my-network
docker network connect my-network container1
## 验证连接是否恢复
docker exec container1 ping -c 2 container2
现在 Ping 应该再次起作用,这演示了容器必须在同一网络上才能进行名称解析。
当遇到容器连接问题时,请遵循此排查清单:
docker psdocker network inspect <network>docker inspect <container>docker exec <container> ping <target>docker exec <container> netstat -tulndocker exec <container> nslookup <target>docker exec <container> iptables -Ldocker logs <container>使用这种系统的方法将帮助你识别和解决大多数容器连接问题。
在这个实验中,你已经学会了如何测试和排查 Docker 容器之间的连接问题。你已经:
这些技能对于开发和维护基于 Docker 的应用程序至关重要,特别是在微服务架构中,多个容器需要相互通信。
为了进一步学习,你可以探索用于多容器应用程序的 Docker Compose、用于容器编排的 Docker Swarm 或 Kubernetes,以及用于多主机部署的更高级网络概念,如覆盖网络。