VPN连接的Docker容器无法访问其他容器

时间:2021-02-19 15:02:04

标签: docker docker-compose vpn

我有一个通过 VPN 容器 (vpn) 连接到 Internet 的应用程序容器 (app)。虽然该连接有效,但应用容器现在无法连接到数据库容器 (db)。

有没有办法让 app 容器连接到本地容器(或任何 RFC1918 地址),同时还通过 vpn 连接?我会简单地将 db 添加到同一个 network_mode 中,但是 db 非常特别需要被另一个未通过 vpn 连接的容器访问(第二个应用程序将从db).

VPN 容器正在运行 bubuntux/nordvpn,我的 docker-compose.yml 如下:

version: "3.9"

services:
  app:
    build: app/
    depends_on:
      - db
    network_mode: service:vpn
    depends_on:
      - vpn
  db:
    image: postgres:alpine
    restart: always
    network_mode: service:vpn
    environment:
      POSTGRES_USER: PASSWORD
      POSTGRES_PASSWORD: PASSWORD
      POSTGRES_DB: PASSWORD
  vpn:
    image: bubuntux/nordvpn
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.conf.all.rp_filter=2
    devices:
      - /dev/net/tun
    environment:
      - USER=EMAIL@EMAIL.COM
      - "PASS=PASSWORD"
      - CONNECT=United_States
      - TECHNOLOGY=NordLynx
    ulimits:
      memlock:
        soft: -1
        hard: -1

我尝试使用 link,如下所示:

app:
   links:
      - db

但是,我收到启动错误,特别是 container type network can't be used with links.

重申这个问题:如何将容器通过 VPN 容器(在本例中为 bubuntux/nordvpn)连接到互联网,该容器也可由非 VPN 连接的容器访问?

谢谢!

3 个答案:

答案 0 :(得分:0)

根据 documentation,这应该有效:

version: "3.9"

services:
  app:
    build: app/
    links:
      - vpn:db     
    depends_on:
      - db
  db:
    image: postgres:alpine
    depends_on:
      - vpn
    restart: always
    network_mode: service:vpn
    environment:
      POSTGRES_USER: PASSWORD
      POSTGRES_PASSWORD: PASSWORD
      POSTGRES_DB: PASSWORD
  vpn:
    image: bubuntux/nordvpn
    network_mode: bridge 
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.conf.all.rp_filter=2
    devices:
      - /dev/net/tun
    environment:
      - USER=EMAIL@EMAIL.COM
      - "PASS=PASSWORD"
      - CONNECT=United_States
      - TECHNOLOGY=NordLynx
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - 5432:5432

你应该从你的机器上访问 localhost:5432 的 postgres

更新

我做这个模拟是因为我无法访问付费的 nordvpn acciut,所以 vpn 服务只是一个休眠 36000 秒的 ubuntu 并且 db 服务正在使用该网络,但是这样我不知道什么是真正的vpn 服务在具有这些附加功能(NET_ADMIN、SYS_MODULE)的主机上执行,但请尝试尝试此设置。

使用此设置应用程序服务(即 adminer,db admin gui)正在侦听我的机器 localhost:8080,我可以登录它并使其连接到具有主机名 db(服务器名称设置为gui) 正在侦听其默认的 5432 postgres 端口。此外,我可以从我的机器 localhost:54320 地址访问 postgres,因为它被转发到应用服务 5432 端口,该端口与使用 vpn 服务网络的 db 服务使用相同的网络,这可能意味着使用 nordvpn 网络。< /p>

version: "3"

services:
  app:
    image: adminer
    restart: always
    ports:
      - 8080:8080
      - 54320:5432
    links:
      - vpn:db     
    depends_on:
      - db
  db:
    image: postgres:alpine
    depends_on:
      - vpn
    restart: always
    network_mode: service:vpn
    environment:
       - POSTGRES_USER=root
       - POSTGRES_PASSWORD=root
       - POSTGRES_DB=mydb
  vpn:
    image: ubuntu
    command: ["/bin/sh","-c","echo started && sleep 36000"]

答案 1 :(得分:0)

这里的问题是 network_mode: service:$name 的工作原理:

它创建了从您的 app 服务到您的 vpn 服务的隐式依赖关系,因此 docker-compose 将首先启动 vpn 容器并连接其自己的网络命名空间和虚拟网络接口到虚拟网络(在本例中为 <project>_default 创建的 docker_compose 网络)。

然后它将启动app容器vpn服务具有相同的网络命名空间,即localhost容器中的vpn是与 localhost 容器中的 app 相同 - 到目前为止,这实际上是您想要的。

现在,由于您也在 network_mode: service:vpn 服务上设置了 db,它也将添加到相同的网络命名空间 - 这不是 strong> 您想要什么,因为容器现在无法通过 DNS 作为 db 被发现,因为它附加到 vpn 的网络命名空间而不是它自己的命名空间。

通过以下方式之一实现您想要的:

  • 第一个选项:从 network_mode: service:vpn 中删除 db,这样服务将获得自己的网络命名空间/内部 IP 地址,可以通过 DNS 解析 - 即您可以使用“db”作为数据库连接的主机名
  • 第二个选项:使用“localhost”作为数据库连接的主机名,因为 appdb 共享相同的网络命名空间,即 localhost 是指一样

对于第一个选项,docker-compose.yml 将如下所示:

version: "3.9"

services:
  app:
    build: app/
    depends_on:
      - db
    network_mode: service:vpn
  db:
    image: postgres:alpine
    restart: always
    environment:
      POSTGRES_USER: PASSWORD
      POSTGRES_PASSWORD: PASSWORD
      POSTGRES_DB: PASSWORD
  vpn:
    image: bubuntux/nordvpn
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.conf.all.rp_filter=2
    devices:
      - /dev/net/tun
    environment:
      - USER=EMAIL@EMAIL.COM
      - "PASS=PASSWORD"
      - CONNECT=United_States
      - TECHNOLOGY=NordLynx
    ulimits:
      memlock:
        soft: -1
        hard: -1

另请注意:

  • links 已弃用,不应用于新应用程序
  • depends_on 将确保依赖服务在依赖服务之前启动 - 但它不是 必需 DNS 解析工作,因此您可以省略它
  • 如果您想为服务更改/分配特定的 DNS 名称,可以使用 aliases

有关更多信息,请参阅 Networking in Compose

答案 2 :(得分:0)

当您在 network_mode: service:vpn 的配置中使用 app 时,appvpn 服务似乎运行在同一个容器网络中(具体来说,它们在相同的网络命名空间)。它们共享接口、路由规则、端口等。值得注意的是,它们还共享 /etc/resolv.conf/etc/hosts。由于 links 只是将相关条目添加到 /etc/hosts,您可以通过(违反直觉)将 app 链接添加到 db 链接到 db {1}} 项服务。

尝试以下配置:

vpn