docker-compose:通过 vpn 路由流量,但与其他服务的连接除外

标签 docker-compose vpn docker-networking

考虑这个 docker-compose 配置:

# docker-compose.yml
version: "3.7"

services:
  app:
    build: ./app
    depends_on:
      - db
      - vpn
    ports:
      - "3001:3000"
  db:
    image: postgres
  vpn:
    build: ./vpn
    cap_add:
      - NET_ADMIN

描述

  • 通过 http://localhost:3001 从 docker 主机访问 app
  • app 需要连接到 postgres db,这是第二个容器。
  • 另外,app 需要连接到一个 api,它只能通过 vpn 访问。这就是第三个容器 vpn 建立所需 vpn 连接的原因。

目标

app 容器应该能够访问此 docker-compose 环境中的其他服务,即 db,并通过 vpn容器,这样它就可以访问vpn隧道后面的api。

我尝试过的

  • 我已尝试设置 appnetwork_mode:

    services:
      app:
        network_mode: "service:vpn"
    

    这会通过 vpn 路由 app 容器的所有流量。这样,我就可以从 app 容器访问 vpn 隧道后面的 api。但这与 ports: - "3001:3000" 不兼容。此外,db 容器无法再从 app 访问:ping: bad address 'db'

  • 我还尝试从 vpn 容器链接 db 容器,希望这将使 db 服务可用到应用

    services:
      app:
        network_mode: "service:vpn"
      vpn:
        links:
          - db
    

    但是 app 仍然找不到 db

  • 如果我从 vpn 容器链接 db 容器,但vpn 中建立 vpn 连接 容器,db 容器可以app 访问。

  • 我已经尝试将 127.0.0.1 db 添加到 app 容器的 /etc/hosts 中,含糊不清希望我可以直接到达 db 端口。但这也行不通。

有没有人知道如何实现这一点?

最佳答案

我终于找到了解决方案,但它需要三个步骤:

第 1 步:网络模式:服务

为了通过vpn路由app容器的所有流量,在app上设置network_mode容器:

services:
  app:
    network_mode: "service:vpn"

第 2 步:DNS 服务器

为了解析 vpn 隧道后面的主机名以及本地 docker 服务,vpn 容器需要与两个 DNS 服务器对话:隧道后面的 DNS 服务器以及docker-compose DNS 服务器。

据我所知,docker-compose DNS 服务器始终是 127.0.0.11

要找出隧道后面的远程 DNS 服务器,请建立隧道,然后运行 ​​cat/etc/resolv.conf。这将在注释为“by strongSwan”的行中列出隧道后面的 DNS 服务器。

vpn容器的启动脚本中,将两个DNS服务器添加到vpn容器的resolv.conf中:

# vpn-container startup script:
echo "nameserver <remote dns server ip>" >> /etc/resolv.conf
echo "nameserver 127.0.0.11" >> /etc/resolv.conf

要对此进行测试,请登录到 vpn 容器并尝试 ping 远程 ip 和 db 容器:

docker-compose run vpn /bin/bash
ping db  # should work
ping <some-ip-behind-the-vpn-tunnel>  # should also work

第三步:暴露端口

app 容器上使用 network_mode: "service:vpn" 时,app 容器无法再将其端口暴露给主机据我了解。相反,app 容器和 vpn 容器现在对 docker 主机显示为同一台机器。因此,可以改为在 vpn 容器上公开所需的端口。

services:
  vpn:
    ports:
      - "3001:3000"

然后可以通过 docker 主机上的 http://localhost:3001 访问 app (!)。

汇集所有内容:最终 docker-compose.yml

# docker-compose.yml
version: "3.7"

services:
  app:
    build: ./app
    depends_on:
      - db
      - vpn
    network_mode: "service:vpn"
  db:
    image: postgres
  vpn:
    build: ./vpn
    cap_add:
      - NET_ADMIN
    ports:
      - "3001:3000"
    command: >
      bash -c "echo 'nameserver <remote dns server ip>' >> /etc/resolv.conf
      && echo 'nameserver 127.0.0.11' >> /etc/resolv.conf
      && ..."

关于docker-compose:通过 vpn 路由流量,但与其他服务的连接除外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69228372/

相关文章:

docker - 无法使 Docker 容器使用 OpenConnect VPN 连接

iphone - 通过 Windows VPN 的 Bonjour

docker-compose chrome-alpine 使用 nginx

用于数据库、日志和指标的 Docker 卷容器

node.js - 远程调试docker容器内运行进程

docker - 在 docker 容器中运行 Scrapy

python - docker-compose 附加后挂起

docker - 调用时将参数传递给docker-compose yml

android.net.conn.CONNECTIVITY_CHANGE 广播接收器不会在 JellyBean 中触发以进行 VPN 连接和断开连接

docker - docker 无法识别默认地址池