Ottavio Miele
Ottavio Miele

Reputation: 38

Docker Swarm: Get IP Address of containers

I need your support. I am building up a business network on a VPS, and I'm using Docker Swarm. In the Swarm environment, there will be a Wireguard VPN service, a DNS server and a bunch of other services that needs to be accessed only through VPN. Here is my file:

version: '3.8'

volumes:
  wireguard_data:
  gitlab_data:
  gitlab_logs:
  gitlab_config:
  traefik-certificates:
  
networks:
    vpn:
        name: vpn
        driver: overlay
        ipam:
          config:
            - subnet: 10.0.1.0/24
services:
    wg-easy:
        environment:
          - LANG=it
          # ⚠️ Required:
          # Change this to your host's public address
          - WG_HOST=localhost

          # Optional:
          - PASSWORD=admin
          # - PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuV4fafBzOHWKu9sbyVa34GJr8VV5R/pIelfEMYyG (needs double $$, hash of 'foobar123'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
          # - PORT=51821
          # - WG_PORT=51820
          # - WG_CONFIG_PORT=92820
          - WG_DEFAULT_ADDRESS=10.0.2.x
          - WG_DEFAULT_DNS=dns.example.com
          # - WG_MTU=1420
          - WG_ALLOWED_IPS=10.0.1.0/24
          # - WG_PERSISTENT_KEEPALIVE=25
          - WG_PRE_UP=iptables -t nat -A POSTROUTING -d 10.0.1.0/24 -j MASQUERADE
          - WG_POST_DOWN=iptables -t nat -D POSTROUTING -d 10.0.1.0/24 -j MASQUERADE
          - UI_TRAFFIC_STATS=true
          - UI_CHART_TYPE=1 # (0 Charts disabled, 1 # Line chart, 2 # Area chart, 3 # Bar chart)

        image: ghcr.io/wg-easy/wg-easy
        container_name: wg-easy
        hostname: 'vpn.example.com'
        depends_on:
            - dnsmasq
        volumes:
          - wireguard_data:/etc/wireguard
        networks:
          - vpn
        ports:
          - "51820:51820/udp"
          - "51821:51821/tcp"
        restart: unless-stopped
        cap_add:
          - NET_ADMIN
          - SYS_MODULE
          # - NET_RAW # ⚠️ Uncomment if using Podman 
        sysctls:
          - net.ipv4.ip_forward=1
          - net.ipv4.conf.all.src_valid_mark=1
        deploy:
          replicas: 1
          labels:
            - "traefik.enable=true"
            - "traefik.udp.routers.wireguard.entrypoints=wireguard"
            - "traefik.udp.services.wireguard.loadbalancer.server.port=51820"
            - "traefik.http.routers.wireguard-ui.rule=Host(`vpn.example.com`)"
            - "traefik.http.routers.wireguard-ui.entrypoints=web"
            - "traefik.http.services.wireguard-ui.loadbalancer.server.port=51821"
    dnsmasq:
        image: dockurr/dnsmasq
        container_name: dnsmasq
        hostname: 'dns.example.com'
        environment:
          DNS1: "1.0.0.1"
          DNS2: "1.1.1.1"
        networks:
          - vpn
        volumes:
          - ./configs/dnsmasq.conf:/etc/dnsmasq.conf
        restart: unless-stopped
        cap_add:
          - NET_ADMIN
        deploy:
          replicas: 1
          labels:
            - "traefik.enable=false"
    gitlab:
        image: gitlab/gitlab-ee:latest
        container_name: gitlab
        restart: always
        hostname: 'gitlab.example.com'
        volumes:
          - gitlab_data:/var/opt/gitlab
          - gitlab_logs:/var/log/gitlab
          - gitlab_config:/etc/gitlab
        shm_size: '256m'
        #environment:
            #GITLAB_OMNIBUS_CONFIG: |
            #    # Add any other gitlab.rb configuration here, each on its own line
            #    external_url 'https://gitlab.example.com'
        networks:
            - vpn
        deploy:
          replicas: 1
          labels:
            - "traefik.enable=true"
            - "traefik.http.routers.gitlab.rule=Host(`gitlab.example.com`)"
            - "traefik.http.routers.gitlab.entrypoints=web"
            - "traefik.http.services.gitlab.loadbalancer.server.port=80"
    whoami:
        image: traefik/whoami
        container_name: whoami
        restart: always
        hostname: 'whoami.example.com'
        networks:
            - vpn
        deploy:
            replicas: 1
            labels:
                - "traefik.enable=true"
                - "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
                - "traefik.http.services.whoami.loadbalancer.server.port=80"
    traefik:
        image: traefik:latest
        command:
          - "--providers.docker=true"
          - "--api.dashboard=true"
          - "--log.level=INFO"
          #- "--log.filepath=/var/log/traefik.log
          - "--accesslog=true"
          #- "--accesslog.filepath=/var/log/traefik-access.log
          - "--providers.docker.exposedByDefault=false"
          - "--providers.docker.network=vpn"
          - "--providers.swarm.endpoint=unix:///var/run/docker.sock"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.dns.address=:53"
          - "--entrypoints.wireguard.address=:51820/udp"
          - "--certificatesresolvers.myresolver.acme.tlschallenge=false"
          - "--certificatesresolvers.myresolver.acme.email=your-email@example.com"
          - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - traefik-certificates:/letsencrypt
        networks:
            - vpn
        deploy:
          #mode: global
          labels:
            - traefik.enable=true
            - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
            - "traefik.http.routers.dashboard.service=api@internal"
            - "traefik.http.services.dummy-svc.loadbalancer.server.port=9999"

As you can see, I'm using DNSMasq to redirect all instances of "example.com" to the Traefik reverse proxy, and I need to configure the DNSMasq instance as default DNS for Wireguard VPN Clients (WG_DEFAULT_DNS variable), but it seems I cannot retrieve IP Addresses of these containers.

The ideal solution would be:

  1. Start Traefik instance, so Swarm assign it an IP in the network (e.g. 10.0.1.100)
  2. Start DNSMasq, passing the IP address of Traefik, so I can configure dnsmasq.conf accordingly (address=/example.com/10.0.1.100). Swarm assign to DNSMasq container an IP (e.g. 10.0.1.2)
  3. Start Wireguard VPN, passing the IP Address of DNSMasq as WG_DEFAULT_DNS variable (e.g. WG_DEFAULT_DNS=10.0.1.2)

Obviously, the order will be managed by depends_on directive, so I'll be sure Wireguard starts once DNSMasq started, and this one starts once Traefik instance started.

With a configuration like that, I'm totally sure that I do not need to reconfigure anything in case of restart/outage/change of IP Addresses.

Is this configuration possible? If I am wrong with some, if not all, of the concepts, please guide me in the right direction to achieve the same objective. I also thought about making DNSMasq as system service on host, instead of Docker Swarm, but I'll still need the Traefik IP to redirect correctly.

Thanks in advance

Upvotes: 0

Views: 152

Answers (0)

Related Questions