使用Docker容器作为网络网关

Orp*_*hid 5 docker docker-compose docker-networking

我想配置一个网关来连接两个容器。下面是一个示例撰写文件,该文件创建了三个容器-一个test_client,一个test_server和一个代理。代理服务器应充当从test_client到test_server的所有通信的默认网关。我正在使用撰写文件格式v2,因为v3不支持IPAM网关配置。

version: "2"
services:
  proxy:
    build: .
    cap_add:
      - NET_ADMIN
    expose:
      - 8080
      - 80
      - 443
    networks:
      client_network:
          ipv4_address: '192.168.0.5'
      server_network: null
    stdin_open: true
    tty: true
  test_server:
    build: ./test_server
    expose:
      - 8000
    networks:
      - server_network
  test_client:
    build: ./test_client
    networks:
      - client_network
    stdin_open: true
    tty: true

networks:
  client_network:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: "192.168.0.0/24"
          gateway: "192.168.0.5"
  server_network:
    driver: bridge
Run Code Online (Sandbox Code Playgroud)

运行时docker-compose up,出现以下错误:

ERROR: for 28e458cec9ac_network_proxy_1  b'user specified IP address is supported only when connecting to networks with user configured subnets'
Run Code Online (Sandbox Code Playgroud)

我已阅读以下资源:

SO: Docker 容器作为两个Docker 桥接器之间的网关Docker论坛

但是他们似乎并没有帮助我回答如何获得此设置。我并没有致力于任何特定的网络结构-我唯一要做的就是配置一个容器充当其他两个容器之间的网络级网关的事物。

dsh*_*erd 9

不幸的是,桥接网络(或任何其他类型的 Docker 网络)并不真正支持这个用例。问题是桥接网络使用您的主机作为网关。它通过为桥接网络上的主机创建虚拟接口并进行一些主机配置来实现必要的路由来实现此目的。该gateway选项仅配置将分配给该虚拟接口的 IP 地址。

这似乎没有很好的记录,我认为它被认为是 docker 网络的实现细节。我从几个论坛帖子中找到了它:来源 1来源 2

编辑:这是我的工作 docker-compose 文件。它有两个专用网络,每个网络都有自己的网关,即alice <-> moon <-> sun <-> bob。神奇之处在于每个容器运行的块内的ip和命令。忽略,它只是一个永远不会完成的命令,这意味着容器将保持运行状态,直到您杀死它。iptablescommand:tail -f /dev/null

version: "3.3"

services:

  alice:
    image: ubuntu-with-tools
    cap_add:
      - NET_ADMIN
    hostname: alice
    networks:
      moon-internal:
        ipv4_address: 172.28.0.3
    command: >-
      sh -c "ip route del default &&
      ip route add default via 172.28.0.2 &&
      tail -f /dev/null"

  moon:
    image: ubuntu-with-tools
    cap_add:
      - NET_ADMIN
    hostname: moon
    networks:
      moon-internal:
        ipv4_address: 172.28.0.2
      internet:
        ipv4_address: 172.30.0.2
    command: >-
      sh -c "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE &&
      iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE &&
      iptables -A FORWARD -i eth1 -j ACCEPT &&
      iptables -A FORWARD -i eth0 -j ACCEPT &&
      ip route add 172.29.0.0/16 via 172.30.0.4 &&
      tail -f /dev/null"


  sun:
    image: ubuntu-with-tools
    cap_add:
      - NET_ADMIN
    hostname: sun
    networks:
      sun-internal:
        ipv4_address: 172.29.0.4
      internet:
        ipv4_address: 172.30.0.4
    command: >-
      sh -c "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE &&
      iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE &&
      iptables -A FORWARD -i eth1 -j ACCEPT &&
      iptables -A FORWARD -i eth0 -j ACCEPT &&
      ip route add 172.28.0.0/16 via 172.30.0.2 &&
      tail -f /dev/null"

  bob:
    image: ubuntu-with-tools
    cap_add:
      - NET_ADMIN
    hostname: bob
    networks:
      sun-internal:
        ipv4_address: 172.29.0.5
    command: >-
      sh -c "ip route del default &&
      ip route add default via 172.29.0.4 &&
      tail -f /dev/null"


networks:
  moon-internal:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16
  sun-internal:
    driver: bridge
    ipam:
      config:
        - subnet: 172.29.0.0/16
  internet:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/16
Run Code Online (Sandbox Code Playgroud)

要尝试一下,请运行docker exec -it ipsec-playground_bob_1 tcpdumpdocker exec -it ipsec-playground_alice_1 ping 172.29.0.5。您应该看到 Alice 的 ping 到达 Bob。

ubuntu-with-tools是一个简单的 ubuntu 映像,其中包含一些我想要安装的东西,这是 Dockerfile:

FROM ubuntu
RUN apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y iproute2 inetutils-ping curl host mtr-tiny tcpdump iptables \
    && rm -rf /var/lib/apt/lists/*
Run Code Online (Sandbox Code Playgroud)