dockerdocker-composenetwork-programmingvpn

docker-compose: images behind VPN unavailable in local network


I have four services in a docker-compose file. vpn_img1 and vpn_img2 are behind a vpn (configured as described below), host_img1 and host_img2 are not.

I am able to access all four 'img' services on the host machine via http://localhost:<port_num> but can only access the 'host_img' images on other machines on the local network; the 'vpn_img' images time out. I get the same result with other, similar vpn images. Does anyone know why? Are there any setting on the vpn service that would allow access to the 'vpn_img' images? Is there something else I need to do to enable that kind of access?

Also, host_img1 needs to talk to the vpn_imgs, but host_img2 does not.

version: "3.4"
services:    
  vpn:
    container_name: vpn
    image: ghcr.io/bubuntux/nordlynx
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    environment:
      - PRIVATE_KEY=xxx
      - QUERY=filters\[country_id\]=228
      - NET_LOCAL=192.168.1.0/24
      # - ALLOWED_IPS=192.168.0.0/24
    ports:
      - 1234:1234 # vpn_img1
      - 2345:2345 # vpn_img2
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=1

  vpn_img1:
    container_name: vpn_img1
    image: vpn_img1
    restart: unless-stopped
    network_mode: service:vpn # run on the vpn network
    depends_on:
      - vpn

  vpn_img2:
    container_name: vpn_img2
    image: vpn_img2
    restart: unless-stopped
    network_mode: service:vpn # run on the vpn network
    depends_on:
      - vpn

  host_img1:
    container_name: host_img1
    image: host_img1
    restart: unless-stopped
    network_mode: host

  host_img2:
    container_name: host_img2
    image: host_img2
    restart: unless-stopped
    network_mode: host

Solution

  • The original answer was removed as its author used generative AI to write it. I will discuss how I solved the issue using the pointers from the previous response.

    I set up a little nginx server to serve the vpn_imgs in a reverse proxy. The nginx.conf file needs to look like the below, with a new location block for each vpn_img. The key piece I had been missing was the $docker_internal_ip for each location.

    events {}
    
    http {
        server {
            resolver 127.0.0.11;  # docker's internal DNS resolver
    
            listen 80;
    
            location ^~ /vpn_img1 {
                set $docker_internal_ip 172.17.0.1;
                set $upstream_port 9876;
                set $upstream_proto http;
                proxy_pass $upstream_proto://$docker_internal_ip:$upstream_port;
    
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $http_connection;
            }
        }
    }