如何测试 Docker 容器之间的连接

DockerDockerBeginner
立即练习

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

简介

Docker 容器已成为现代应用程序开发和部署的基本组成部分。在处理多个容器时,确保它们之间的正确连接对于应用程序的正常运行至关重要。

在本实验中,你将学习如何验证和排查 Docker 容器之间的连接问题。我们将从基本的 Docker 容器概念开始,设置用于测试的容器,然后探索各种方法来检查和诊断容器之间的网络连接。

在本教程结束时,你将能够自信地测试、验证和解决容器化应用程序中的连接问题。

本实验需要互联网连接才能进行学习,因此只有专业版用户才能启动虚拟机。将你的账户升级为专业版


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/NetworkOperationsGroup(["Network Operations"]) docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/ls("List Containers") docker/ContainerOperationsGroup -.-> docker/ps("List Running Containers") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/NetworkOperationsGroup -.-> docker/network("Manage Networks") subgraph Lab Skills docker/run -.-> lab-411613{{"如何测试 Docker 容器之间的连接"}} docker/ls -.-> lab-411613{{"如何测试 Docker 容器之间的连接"}} docker/ps -.-> lab-411613{{"如何测试 Docker 容器之间的连接"}} docker/exec -.-> lab-411613{{"如何测试 Docker 容器之间的连接"}} docker/inspect -.-> lab-411613{{"如何测试 Docker 容器之间的连接"}} docker/network -.-> lab-411613{{"如何测试 Docker 容器之间的连接"}} end

设置用于测试的 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

这些命令:

  1. 使用 docker exec 在正在运行的容器内运行命令
  2. 使用 apt-get update 更新软件包列表
  3. 安装网络工具(iputils-ping 用于 ping 命令,net-tools 用于 netstat 命令,iproute2 用于 IP 相关命令,以及 curl

现在我们的容器已准备好进行下一步的连接测试。

理解 Docker 网络

Docker 容器通过网络相互通信。了解 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 地址

为了处理容器连接,我们需要知道分配给容器的 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 开头。

创建自定义 Docker 网络

虽然默认桥接网络允许容器通信,但创建自定义网络可提供更好的隔离和内置 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 测试连接

测试基本网络连接的最简单方法是使用 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

测试 DNS 解析

自定义 Docker 网络的一个优点是它们提供自动 DNS 解析,允许容器通过名称相互访问。

让我们通过按名称 Ping 容器来测试 DNS 解析:

docker exec container1 ping -c 4 container2

这应该可行,因为两个容器都在我们的自定义 my-network 上,该网络提供 DNS 解析。你应该会看到与之前测试类似的 Ping 响应,但使用的是容器名称而不是 IP。

使用 curl 测试 HTTP 连接

对于运行 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 容器网络时,你可能会遇到几个常见问题:

  1. 不同网络上的容器没有正确的路由
  2. 防火墙或安全组设置阻止了流量
  3. 应用程序没有在预期的 IP/端口上监听
  4. 网络配置错误
  5. DNS 解析问题

让我们针对这些潜在问题逐一进行排查步骤。

检查网络配置

首先,让我们检查容器的网络配置:

## 查看 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 进行诊断

为了进行更详细的网络流量分析,我们可以使用 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 数据包。

检查 Docker DNS 解析

如果你在容器之间的 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 应该再次起作用,这演示了容器必须在同一网络上才能进行名称解析。

排查清单

当遇到容器连接问题时,请遵循此排查清单:

  1. 验证容器正在运行docker ps
  2. 检查它们是否在同一网络上docker network inspect <network>
  3. 验证是否已分配 IP 地址docker inspect <container>
  4. 测试基本连接(Ping)docker exec <container> ping <target>
  5. 检查应用程序是否正在监听docker exec <container> netstat -tuln
  6. 验证 DNS 解析是否正常工作docker exec <container> nslookup <target>
  7. 查找防火墙问题docker exec <container> iptables -L
  8. 检查容器日志docker logs <container>

使用这种系统的方法将帮助你识别和解决大多数容器连接问题。

总结

在这个实验中,你已经学会了如何测试和排查 Docker 容器之间的连接问题。你已经:

  • 创建了 Docker 容器并为其配置了网络
  • 了解了 Docker 网络基础,包括默认网络和自定义网络
  • 使用了各种工具来测试容器之间的基本连接(ping、curl、netcat)
  • 探讨了常见的连接问题并学习了系统的排查方法

这些技能对于开发和维护基于 Docker 的应用程序至关重要,特别是在微服务架构中,多个容器需要相互通信。

为了进一步学习,你可以探索用于多容器应用程序的 Docker Compose、用于容器编排的 Docker Swarm 或 Kubernetes,以及用于多主机部署的更高级网络概念,如覆盖网络。