{"msg":"操作成功","code":200,"data":{"createBy":"admin","createTime":"2021-05-24 12:52:07","updateBy":"admin","updateTime":"2025-09-12 14:20:07","remark":null,"id":61,"articleTitle":"Docker（七）网络管理","articleUrl":"docker_network","articleThumbnail":"https://www.asumimoe.com/imgfiles/20220906/713782e83c4e4b9bbf2d588c2789e07d.jpg","articleFlag":"0","draftStatus":"1","reprintStatement":"1","articleSummary":"docker网络隔离基于网络命名空间，在物理机上创建docker容器时会为每一个docker容器分配网络命名空间，并且把容器IP桥接到物理机的虚拟网桥上。容器默认网络模式为bridge模式","articleContent":"## Docker 网络模式概览\n\nDocker 提供了多种网络模式，以满足不同场景下的容器通信需求。以下是五种主要模式及其特点的对比：\n\n| **网络模式**  | **简介**                                                 | **适用场景**                                                 | **优点**                         | **缺点**                                 |\n| :------------ | :------------------------------------------------------- | :----------------------------------------------------------- | :------------------------------- | :--------------------------------------- |\n| **bridge**    | Docker **默认**的网络模式，通过 **docker0 网桥**连接容器 | **单主机**内容器间的通信                                     | 隔离性好，配置灵活               | 跨主机通信需额外配置，NAT 转换有性能损耗 |\n| **host**      | 容器直接使用**宿主机网络命名空间**                       | 需要**高性能网络**或直接使用主机端口的场景                   | 网络性能最好，无NAT损耗          | 容器与主机端口冲突风险，网络隔离性差     |\n| **container** | 容器共享另一个容器的网络命名空间                         | 需要**紧密协作**且共享网络的容器组（如日志收集器与应用容器） | 容器间高效通信，共享网络栈       | 网络隔离性差，依赖性高                   |\n| **none**      | 禁用所有网络，容器只有**lo回环接口**                     | 需要**完全自定义网络**或处理极度敏感数据的场景               | 安全性最高，完全自主控制网络配置 | 需要手动配置所有网络参数，复杂度高       |\n| **overlay**   | 支持**跨多主机**的容器网络，基于 **VXLAN** 隧道技术      | ** Docker Swarm **或其他集群环境中的服务发现和通信           | 良好的跨主机通信和扩展性         | 配置和管理相对复杂                       |\n\n## 核心网络管理命令\n\n以下命令帮助你管理 Docker 网络：\n\n| 命令                        | 功能描述             | 示例                                                         |\n| :-------------------------- | :------------------- | :----------------------------------------------------------- |\n| `docker network ls`         | 列出所有网络         | `docker network ls`                                          |\n| `docker network create`     | 创建新网络           | `docker network create -d bridge --subnet 192.168.100.0/24 mynet` |\n| `docker network inspect`    | 查看网络详细信息     | `docker network inspect mynet`                               |\n| `docker network connect`    | 将容器连接到网络     | `docker network connect mynet container1`                    |\n| `docker network disconnect` | 断开容器与网络的连接 | `docker network disconnect mynet container1`                 |\n| `docker network rm`         | 删除网络             | `docker network rm mynet`                                    |\n| `docker network prune`      | 删除所有未使用的网络 | `docker network prune`                                       |\n\n## 自定义网络与实践建议\n\n### 1. 创建自定义网络\n\n建议创建自定义的 bridge 网络而非使用默认的 `bridge`，因为**自定义网络支持自动 DNS 解析**，容器间可以通过容器名互相访问。\n\n```bash\n# 创建自定义bridge网络，并指定子网和网关\ndocker network create -d bridge --subnet 192.168.100.0/24 --gateway 192.168.100.1 mynet\n# 在自定义网络中运行容器\ndocker run -d --name web-app --network mynet -p 8080:80 my-web-image\ndocker run -d --name redis-cache --network mynet redis:alpine\n# 此时在web-app容器中可以直接 ping redis-cache\n```\n\n### 2. 容器网络连通\n\n`docker network connect` 命令可以让一个**已运行**的容器加入到一个**已存在**的网络中，从而实现容器与特定网络的连通。\n\n```bash\n# 将一个正在运行的容器连接到某个网络\ndocker network connect mynet existing-container\n```\n\n### 3. 查看端口映射\n\n使用 `docker port` 命令查看容器的端口映射情况。\n\n```bash\ndocker port <container-name-or-id>\ndocker port <container-name-or-id> 80 # 查看容器80端口映射到宿主的哪个端口\n```\n\n## 容器端口映射\n\n要让外部网络访问容器内服务，需要进行端口映射。\n\n### 映射方法\n\n1. **运行容器时映射 (`docker run -p`)**\n   这是最常用的方法，在启动容器时通过 `-p` 或 `-P` 参数指定端口映射。\n\n   * **`-P` (大写)**：**随机映射**。Docker 会将容器暴露的所有端口（`EXPOSE` 指令声明的端口）随机映射到宿主的**高端端口**（通常高于32768）。\n\n     ```bash\n     docker run -d -P --name my-nginx nginx  # 映射到宿主机随机端口\n     docker port my-nginx  # 查看具体映射关系\n     ```\n\n   * **`-p` (小写)**：**指定映射**。可以精确控制映射关系，格式为 `-p [宿主IP:][宿主端口:]<容器端口>[/协议]`。\n\n     ```bash\n     docker run -d -p 8080:80 nginx  # 宿主机8080 -> 容器80\n     docker run -d -p 192.168.1.100:8080:80 nginx  # 绑定特定宿主IP\n     docker run -d -p 8080:80/tcp -p 8080:80/udp nginx  # 指定TCP/UDP\n     ```\n\n2. **为已运行容器添加映射**\n   Docker 本身**不支持**直接为已运行的容器添加端口映射。若需添加，通常需要：\n\n   *   **重新创建容器**：先停止并删除当前容器，再用新的端口映射参数重新运行。\n   *   **修改底层配置（不推荐）**：直接修改 Docker 的配置文件（如 `/var/lib/docker/containers/[container_id]/hostconfig.json`）并重启 Docker 服务，但这**有风险且非官方推荐**。\n\n## 容器之间的通信\n\n### 通过 Docker 网络进行通信（推荐方式）\n\n这是最常用且官方推荐的通信方式。Docker 提供了内置的 DNS 服务，允许容器通过**容器名**直接相互发现和通信。\n\n#### 1. 默认桥接网络 (`bridge`)\n\nDocker 安装后会自动创建一个名为 `bridge` 的默认网络。连接到这个网络的容器可以通过 **IP 地址** 相互通信。\n\n*   **通信方式**：使用对方容器的 IP 地址。\n*   **缺点**：**不支持通过容器名访问**，必须使用 `docker inspect` 来查找 IP，非常不灵活。\n\n**示例：**\n\n```bash\n# 启动两个容器，它们默认都会连接到 `bridge` 网络\ndocker run -d --name container1 nginx\ndocker run -it --name container2 alpine\n\n# 在 container2 中 ping container1 的 IP (无法通过容器名)\n/ # ping 172.17.0.2\n```\n\n#### 2. 自定义桥接网络 (`user-defined bridge`)\n\n**这是生产环境中最推荐的容器间通信方式。** 你可以创建自己的桥接网络，其最大优势是**内置自动服务发现**。\n\n*   **通信方式**：直接使用**容器名**作为主机名。\n*   **优点**：\n    *   **自动 DNS 解析**：容器可以通过容器名或别名(`--network-alias`)相互解析。\n    *   **更好的隔离性**：将不同应用的容器隔离在不同的网络中，更安全。\n    *   **自动附加**：可以动态地将容器连接或断开与自定义网络的连接。\n\n**示例：**\n\n```bash\n# 1. 创建一个自定义网络\ndocker network create my-app-network\n\n# 2. 将容器启动并连接到这个网络\ndocker run -d --name web-server --network my-app-network nginx\ndocker run -d --name app --network my-app-network my-python-app\ndocker run -it --name debug-tool --network my-app-network alpine\n\n# 3. 在 debug-tool 容器中，可以直接通过容器名 ping 通其他容器\n/ # ping web-server\nPING web-server (172.21.0.2): 56 data bytes\n64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.091 ms\n\n/ # ping app\nPING app (172.21.0.3): 56 data bytes\n64 bytes from 172.21.0.3: seq=0 ttl=64 time=0.087 ms\n\n# 4. 在 Python 应用 (app) 的代码中，可以直接通过 `http://web-server` 访问 Nginx\n```\n\n#### 3. 主机网络 (`host`)\n\n使用 `--network=host` 参数，容器不会拥有独立的网络命名空间，而是直接共享宿主机的网络栈。\n\n*   **通信方式**：容器间通过宿主机的 `localhost` (127.0.0.1) 直接通信。\n*   **优点**：网络性能最好，无 NAT 损耗。\n*   **缺点**：**安全性差**，容器端口直接暴露给主机，容易引发端口冲突。\n\n**示例：**\n\n```bash\n# 在主机上运行一个容器，监听主机的 80 端口\ndocker run -d --network host nginx\n\n# 运行另一个容器，它可以通过 localhost:80 直接访问 Nginx\ndocker run --network host curlimages/curl curl http://localhost:80\n```\n\n#### 4. 容器网络 (`container`)\n\n使用 `--network=\"container:<name|id>\"` 参数，新创建的容器会共享指定容器的网络命名空间。\n\n*   **通信方式**：共享同一个 IP 和端口范围，直接通过 `localhost` 访问对方。\n*   **适用场景**：非常紧密的容器协作，例如一个容器为另一个提供网络代理或 sidecar 模式。\n\n**示例：**\n\n```bash\n# 启动一个 Nginx 容器\ndocker run -d --name web nginx\n\n# 启动一个调试工具容器，共享 web 容器的网络\ndocker run -it --network container:web nicolaka/netshoot\n\n# 在 netshoot 容器中，可以直接使用 localhost 访问 web 容器的 80 端口\ncurl http://localhost\n```\n\n### 通过共享数据卷（Volume）通信\n\n如果容器间需要共享的是**数据文件**而不是网络请求，那么数据卷是更好的选择。\n\n*   **通信方式**：多个容器挂载同一个数据卷或绑定挂载到同一个宿主目录，通过读写文件来交换数据。\n*   **适用场景**：日志收集、数据处理流水线、共享静态资产等。\n\n**示例：**\n\n```bash\n# 创建一个数据卷\ndocker volume create shared-data\n\n# 容器 A 向数据卷写入数据\ndocker run -v shared-data:/data --name producer alpine sh -c \"echo 'Hello World' > /data/message.txt\"\n\n# 容器 B 从同一个数据卷读取数据\ndocker run -v shared-data:/data --name consumer alpine cat /data/message.txt\n# 输出：Hello World\n```\n\n### 容器通信方式对比与选择\n\n| **通信方式**     | **使用方法**                          | **优点**                         | **缺点**                          | **适用场景**                       |\n| :--------------- | :------------------------------------ | :------------------------------- | :-------------------------------- | :--------------------------------- |\n| **自定义网络**   | `docker network create` + `--network` | **自动服务发现**，隔离性好，灵活 | 需要手动创建网络                  | **绝大多数场景**，特别是微服务应用 |\n| **默认桥接网络** | 默认                                  | 无需配置，简单                   | 只能用 IP，无法用容器名，隔离性差 | 简单的测试和学习                   |\n| **主机网络**     | `--network=host`                      | **性能极致**，无 NAT             | **安全性差**，端口冲突            | 需要极高网络性能的特殊应用         |\n| **容器网络**     | `--network=container:<name>`          | 紧密集成，高效                   | 网络栈完全共享，耦合度高          | Sidecar 模式，网络代理             |\n| **--link**       | `--link`                              | 可在旧默认网络中用容器名         | **已废弃**，单向，脆弱            | **不推荐使用**，仅用于兼容旧项目   |\n| **共享数据卷**   | `-v volume_name:/path`                | 适合**大数据量**、文件共享       | 不适合实时通信                    | 日志收集、数据处理、共享文件       |\n\n","categoryId":9,"viewCount":1239,"categoryName":"Docker","author":"球接子","authorAvatar":null,"tagIds":[9],"tagNames":["Docker"]}}