DockerCompose网络配置Skill docker-compose-networking

此技能用于配置和管理Docker Compose中的网络和服务通信,包括默认桥接网络、自定义网络、网络别名、静态IP地址、外部网络、主机网络模式、服务发现、DNS配置等。适用于开发、部署和维护多容器应用程序,实现网络隔离、安全通信和可扩展架构,关键词包括Docker Compose、网络配置、服务通信、容器网络、微服务架构。

Docker/K8s 0 次安装 0 次浏览 更新于 3/25/2026

名称: docker-compose-networking 用户可调用: false 描述: 使用当配置Docker Compose中的网络和服务通信时,包括桥接网络、覆盖网络、服务发现和服务间通信。 允许工具: [Bash, Read]

Docker Compose 网络配置

掌握 Docker Compose 中的网络配置和服务通信模式,用于构建安全、可扩展的多容器应用程序。

默认桥接网络

Docker Compose 自动为 compose 文件中的所有服务创建一个默认桥接网络:

version: '3.8'

services:
  frontend:
    image: nginx:alpine
    ports:
      - "80:80"
    # 可以使用服务名称作为主机名到达后端

  backend:
    image: node:18-alpine
    command: node server.js
    # 从前端可通过主机名 'backend' 访问

  database:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD: secret
    # 从后端可通过主机名 'database' 访问

在此设置中:

  • 所有服务可以使用服务名称作为主机名进行通信
  • 前端可以到达后端在 http://backend:3000
  • 后端可以到达数据库在 postgres://database:5432
  • 只有前端的端口 80 暴露给主机

自定义桥接网络

定义自定义网络以实现服务隔离和分段:

version: '3.8'

services:
  frontend:
    image: nginx:alpine
    networks:
      - frontend-network
    ports:
      - "80:80"

  api:
    image: node:18-alpine
    networks:
      - frontend-network
      - backend-network
    environment:
      DATABASE_URL: postgresql://db:5432/app

  database:
    image: postgres:15-alpine
    networks:
      - backend-network
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app
    volumes:
      - db-data:/var/lib/postgresql/data

  cache:
    image: redis:7-alpine
    networks:
      - backend-network
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data

networks:
  frontend-network:
    driver: bridge
  backend-network:
    driver: bridge
    internal: true

volumes:
  db-data:
  redis-data:

网络隔离:

  • 前端只能到达 API
  • 前端不能直接到达数据库或缓存
  • API 可以到达所有服务
  • 后端网络是内部的(无外部访问)

网络别名

配置多个主机名以进行服务发现:

version: '3.8'

services:
  web:
    image: nginx:alpine
    networks:
      public:
        aliases:
          - website
          - www
          - web-server
      internal:
        aliases:
          - web-internal

  api:
    image: node:18-alpine
    networks:
      public:
        aliases:
          - api-server
          - backend
      internal:
        aliases:
          - api-internal
    depends_on:
      - database

  database:
    image: postgres:15-alpine
    networks:
      internal:
        aliases:
          - db
          - postgres
          - primary-db
    environment:
      POSTGRES_PASSWORD: secret

networks:
  public:
    driver: bridge
  internal:
    driver: bridge
    internal: true

服务可以通过其任何别名访问:

  • http://website, http://www, http://web-server 都到达 web 服务
  • postgresql://db:5432, postgresql://postgres:5432 都到达数据库

静态 IP 地址

为需要稳定网络的服务分配固定 IP 地址:

version: '3.8'

services:
  loadbalancer:
    image: nginx:alpine
    networks:
      app-network:
        ipv4_address: 172.28.1.10
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro

  app-1:
    image: myapp:latest
    networks:
      app-network:
        ipv4_address: 172.28.1.11
    environment:
      APP_ID: "1"

  app-2:
    image: myapp:latest
    networks:
      app-network:
        ipv4_address: 172.28.1.12
    environment:
      APP_ID: "2"

  app-3:
    image: myapp:latest
    networks:
      app-network:
        ipv4_address: 172.28.1.13
    environment:
      APP_ID: "3"

  database:
    image: postgres:15-alpine
    networks:
      app-network:
        ipv4_address: 172.28.1.20
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  app-network:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
          gateway: 172.28.1.1

volumes:
  pgdata:

外部网络

连接到在 Compose 外部创建的现有 Docker 网络:

version: '3.8'

services:
  api:
    image: node:18-alpine
    networks:
      - app-network
      - shared-network
    environment:
      DATABASE_URL: postgresql://db:5432/app

  database:
    image: postgres:15-alpine
    networks:
      - app-network
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  app-network:
    driver: bridge

  shared-network:
    external: true
    name: company-shared-network

volumes:
  pgdata:

首先创建外部网络:

docker network create company-shared-network
docker compose up -d

主机网络模式

使用主机网络以获得最大性能(仅限 Linux):

version: '3.8'

services:
  high-performance-app:
    image: myapp:latest
    network_mode: "host"
    environment:
      BIND_ADDRESS: "0.0.0.0"
      PORT: "8080"
    # 不需要端口映射 - 直接使用主机的网络堆栈

  monitoring:
    image: prometheus:latest
    network_mode: "host"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.listen-address=0.0.0.0:9090'

volumes:
  prometheus-data:

注意:主机网络绕过 Docker 网络隔离,通常用于监控工具或高吞吐量应用程序。

服务发现和 DNS

配置 DNS 解析和服务发现:

version: '3.8'

services:
  api:
    image: node:18-alpine
    networks:
      - app-network
    dns:
      - 8.8.8.8
      - 8.8.4.4
    dns_search:
      - company.local
    extra_hosts:
      - "legacy-api.company.local:192.168.1.100"
      - "auth-service.company.local:192.168.1.101"
    environment:
      DATABASE_HOST: database.company.local

  database:
    image: postgres:15-alpine
    networks:
      app-network:
        aliases:
          - database.company.local
          - db.company.local
    hostname: primary-database
    domainname: company.local
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  app-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-company-app

volumes:
  pgdata:

链接容器(遗留)

虽然 links 已弃用,但理解它有助于迁移遗留配置:

version: '3.8'

services:
  # 现代方法 - 使用网络代替
  web:
    image: nginx:alpine
    networks:
      - app-network
    depends_on:
      - api

  api:
    image: node:18-alpine
    networks:
      - app-network
    depends_on:
      - database
    environment:
      # 使用服务名称作为主机名
      DATABASE_URL: postgresql://database:5432/app

  database:
    image: postgres:15-alpine
    networks:
      - app-network
    environment:
      POSTGRES_PASSWORD: secret

networks:
  app-network:
    driver: bridge

多网络架构

具有多个隔离网络的复杂应用程序:

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    networks:
      - public
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - frontend
      - api

  frontend:
    image: react-app:latest
    networks:
      - public
      - frontend-tier
    environment:
      API_URL: http://api:3000

  api:
    image: node-api:latest
    networks:
      - frontend-tier
      - backend-tier
    environment:
      DATABASE_URL: postgresql://postgres:5432/app
      REDIS_URL: redis://cache:6379
      QUEUE_URL: amqp://rabbitmq:5672
    depends_on:
      - database
      - cache
      - queue

  worker:
    image: node-worker:latest
    networks:
      - backend-tier
    environment:
      DATABASE_URL: postgresql://postgres:5432/app
      QUEUE_URL: amqp://rabbitmq:5672
    depends_on:
      - database
      - queue
    deploy:
      replicas: 3

  database:
    image: postgres:15-alpine
    networks:
      - backend-tier
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app
    volumes:
      - pgdata:/var/lib/postgresql/data

  cache:
    image: redis:7-alpine
    networks:
      - backend-tier
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data

  queue:
    image: rabbitmq:3-management-alpine
    networks:
      - backend-tier
      - management
    ports:
      - "15672:15672"  # 管理界面
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: secret
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq

  monitoring:
    image: prometheus:latest
    networks:
      - management
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus

networks:
  public:
    driver: bridge
  frontend-tier:
    driver: bridge
    internal: true
  backend-tier:
    driver: bridge
    internal: true
  management:
    driver: bridge

volumes:
  pgdata:
  redis-data:
  rabbitmq-data:
  prometheus-data:

网络分段:

  • 公共: 面向互联网的服务(nginx, 前端)
  • 前端层: 前端和 API 通信
  • 后端层: API, 工作者, 数据库, 缓存, 队列
  • 管理: 监控和管理工具

端口发布策略

控制服务如何暴露端口:

version: '3.8'

services:
  # 短语法 - 主机:容器
  web:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    networks:
      - public

  # 长语法,指定协议
  api:
    image: node:18-alpine
    ports:
      - target: 3000
        published: 3000
        protocol: tcp
        mode: host
    networks:
      - app-network

  # 随机主机端口
  app:
    image: myapp:latest
    ports:
      - "3000"  # Docker 分配随机主机端口
    networks:
      - app-network

  # 绑定到特定主机接口
  admin:
    image: admin-panel:latest
    ports:
      - "127.0.0.1:8080:80"  # 仅可从本地主机访问
    networks:
      - admin-network

  # UDP 协议
  dns:
    image: bind9:latest
    ports:
      - "53:53/udp"
      - "53:53/tcp"
    networks:
      - dns-network

  # 端口范围
  streaming:
    image: rtmp-server:latest
    ports:
      - "1935:1935"
      - "8080-8089:8080-8089"
    networks:
      - streaming-network

networks:
  public:
  app-network:
  admin-network:
    internal: true
  dns-network:
  streaming-network:

容器通信模式

请求-响应模式

version: '3.8'

services:
  gateway:
    image: nginx:alpine
    networks:
      - frontend
    ports:
      - "80:80"
    volumes:
      - ./nginx-gateway.conf:/etc/nginx/nginx.conf:ro

  service-a:
    image: service-a:latest
    networks:
      - frontend
      - backend
    environment:
      SERVICE_B_URL: http://service-b:8080
      DATABASE_URL: postgresql://db:5432/service_a

  service-b:
    image: service-b:latest
    networks:
      - frontend
      - backend
    environment:
      DATABASE_URL: postgresql://db:5432/service_b

  database:
    image: postgres:15-alpine
    networks:
      - backend
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  pgdata:

发布-订阅模式

version: '3.8'

services:
  publisher:
    image: publisher:latest
    networks:
      - messaging
    environment:
      REDIS_URL: redis://redis:6379
    depends_on:
      - redis

  subscriber-1:
    image: subscriber:latest
    networks:
      - messaging
    environment:
      REDIS_URL: redis://redis:6379
      SUBSCRIBER_ID: "1"
    depends_on:
      - redis

  subscriber-2:
    image: subscriber:latest
    networks:
      - messaging
    environment:
      REDIS_URL: redis://redis:6379
      SUBSCRIBER_ID: "2"
    depends_on:
      - redis

  redis:
    image: redis:7-alpine
    networks:
      - messaging
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data

networks:
  messaging:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.enable_icc: "true"

volumes:
  redis-data:

网络故障排除配置

启用调试和监控:

version: '3.8'

services:
  app:
    image: myapp:latest
    networks:
      app-network:
        aliases:
          - primary-app
    cap_add:
      - NET_ADMIN
      - NET_RAW

  debug:
    image: nicolaka/netshoot:latest
    networks:
      - app-network
    command: sleep infinity
    cap_add:
      - NET_ADMIN
      - NET_RAW
    stdin_open: true
    tty: true

  database:
    image: postgres:15-alpine
    networks:
      app-network:
        aliases:
          - db
    environment:
      POSTGRES_PASSWORD: secret

networks:
  app-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.enable_ip_masquerade: "true"
      com.docker.network.driver.mtu: "1500"
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

调试命令:

# 进入调试容器
docker compose exec debug bash

# 测试连通性
ping app
curl http://app:8080/health

# 检查 DNS 解析
nslookup app
dig app

# 网络扫描
nmap -p- app

# 路由追踪
traceroute app

# 监控流量
tcpdump -i eth0 -n

IPv6 网络

启用 IPv6 支持:

version: '3.8'

services:
  web:
    image: nginx:alpine
    networks:
      - ipv6-network
    ports:
      - "80:80"

  api:
    image: node:18-alpine
    networks:
      ipv6-network:
        ipv6_address: 2001:db8:1::10

  database:
    image: postgres:15-alpine
    networks:
      ipv6-network:
        ipv6_address: 2001:db8:1::20
    environment:
      POSTGRES_PASSWORD: secret

networks:
  ipv6-network:
    driver: bridge
    enable_ipv6: true
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
        - subnet: 2001:db8:1::/64

何时使用此技能

使用 docker-compose-networking 当您需要:

  • 为多容器应用程序配置自定义网络拓扑
  • 实施网络分段和服务隔离
  • 设置服务发现和服务间通信
  • 设计具有前端/后端分离的安全网络架构
  • 配置服务的静态 IP 地址
  • 连接到外部 Docker 网络
  • 实现复杂的微服务通信模式
  • 排除网络连接问题
  • 配置 DNS 解析和主机名别名
  • 设置发布-订阅或消息队列架构
  • 启用 IPv6 网络
  • 通过主机网络优化网络性能
  • 配置端口发布和暴露策略

最佳实践

  1. 使用自定义网络进行隔离:始终创建自定义网络,而不是仅依赖默认网络,以获得更好的安全性和组织性。

  2. 实施网络分段:将前端、后端和数据层分离到不同的网络中,以限制攻击面。

  3. 使用内部网络:将后端网络标记为 internal: true,以防止外部访问敏感服务,如数据库。

  4. 优先使用服务名称而非 IP:使用 Docker 的内置 DNS 和服务名称,而不是硬编码 IP 地址,以提高可维护性。

  5. 配置健康检查:实施健康检查,确保服务在路由流量之前准备就绪。

  6. 使用网络别名:为服务定义有意义的别名,以支持多种命名约定和更轻松的迁移。

  7. 除非必要,避免主机网络:默认使用桥接网络;主机网络应仅用于特定的性能要求。

  8. 记录网络架构:清楚地注释您的网络设计,并记录哪些服务可以相互通信。

  9. 明智使用 Depends_on:将 depends_on 与健康检查结合使用,确保服务以正确的顺序启动。

  10. 实施最小权限:只暴露绝对需要从 Docker 网络外部访问的端口。

  11. 使用环境变量配置 URL:通过环境变量配置服务端点,以便在不同环境之间灵活配置。

  12. 测试网络隔离:定期验证服务只能通过预期的网络路径通信。

  13. 配置适当的 MTU:根据您的网络基础设施设置 MTU 值,以避免分片问题。

  14. 为共享资源使用外部网络:当多个 Compose 项目需要通信时,使用外部网络而不是重复服务。

  15. 监控网络性能:使用工具如 docker stats 和专用监控容器来跟踪网络使用情况和识别瓶颈。

常见陷阱

  1. 公开所有服务:不要为只应内部访问的服务发布端口;使用网络而不是端口发布。

  2. 硬编码 IP 地址:除非绝对必要,避免静态 IP 地址;依赖服务发现。

  3. 仅使用默认网络:不创建自定义网络会错过适当的隔离机会。

  4. 忽略网络模式:为您的用例使用错误的网络模式(桥接 vs 主机 vs 覆盖)可能导致连接或性能问题。

  5. 缺少网络依赖:未正确配置 depends_on 可能导致服务在尝试连接到不可用服务时失败。

  6. 过度使用主机网络:不必要地使用 network_mode: host 会破坏容器隔离和可移植性。

  7. 不使用内部网络:未将后端网络标记为内部,会暴露数据库和敏感服务。

  8. 混合网络模式:在使用 network_mode: host 时尝试发布端口或连接到网络会导致配置错误。

  9. 循环网络依赖:创建形成循环的网络依赖关系会阻止容器正常启动。

  10. 忽略 DNS 配置:未正确配置 DNS 可能导致容器化应用程序中的名称解析失败。

  11. 子网冲突:使用与主机或其他 Docker 网络冲突的 IP 范围会导致路由问题。

  12. 不测试网络策略:假设网络隔离有效而不测试,可能会留下安全漏洞。

  13. 暴露管理界面:发布管理端口(如 RabbitMQ、Redis、PostgreSQL)而没有身份验证或 IP 限制。

  14. 使用链接而非网络:已弃用的 links 功能应替换为现代网络配置。

  15. 忽略网络驱动选项:未配置驱动选项如 MTU 或 IP 伪装,可能导致生产中的微妙连接问题。

资源

官方文档

网络故障排除

架构模式

工具