Docker Compose with multiple VPN network for multiple services

I have a docker-compose file like this:

version: '3'

services:

  zookeeper:
    image: wurstmeister/zookeeper
    container_name: zookeeper
    restart: always
    ports:
      - 2181:2181

  kafka:
    image: wurstmeister/kafka
    container_name: kafka
    restart: always
    ports:
      - 9092:9092
    depends_on:
      - zookeeper
    links:
      - zookeeper:zookeeper
    environment:
      KAFKA_ADVERTISED_HOST_NAME: kafka
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181

  consumer1:
    image: consumer:0.0.1-SNAPSHOT
    container_name: consumer1
    restart: always
    ports:
      - 8081:8081
    environment:
      SERVER_PORT: 8081
      ADMIN_URL: server
      ADMIN_CLIENT_NAME: counsumer1
    depends_on:
      - kafka
      - vpn1
    links:
      - kafka:kafka
      - server:server

  consumer2:
    image: consumer:0.0.1-SNAPSHOT
    container_name: consumer2
    restart: always
    ports:
      - 8082:8082 
    environment:
      SERVER_PORT: 8082
      ADMIN_URL: server
      ADMIN_CLIENT_NAME: counsumer2
    depends_on:
      - kafka
    links:
      - kafka:kafka
      - server:server


  producer:
    image: producer:0.0.1-SNAPSHOT
    container_name: producer
    restart: always
    ports:
      - 8080:8080
    environment:
      SERVER_PORT: 8080
    depends_on:
      - kafka
    links:
      - kafka:kafka
      

  server:
    image: server:0.0.1-SNAPSHOT
    container_name: server
    restart: always
    ports:
      - 8070:8070
    environment:
      SERVER_PORT: 8070
    depends_on:
      - kafka
    links:
      - kafka:kafka

Then I would like to setup NordVPN containers for each consumer so I will be able to set different external IP for them. How should I do this?

The NordVPN instance can be started:

docker run -ti --cap-add=NET_ADMIN --device /dev/net/tun --name vpn \
           -e USER=user@email.com -e PASS=password \
           -e RANDOM_TOP=n -e RECREATE_VPN_CRON=string \
           -e COUNTRY=country1;country2 -e GROUP=group \
           -e TECHNOLOGY=technology -d azinchen/nordvpn

Once it’s up other containers can be started using it’s network connection:

docker run -it --net=container:vpn -d some/docker-container

Or by docker-compose:

version: "3"
services:
  vpn:
    image: azinchen/nordvpn:latest
    cap_add:
      - net_admin
    devices:
      - /dev/net/tun
    environment:
      - USER=user@email.com
      - PASS=password
      - COUNTRY=Spain;Hong Kong;IE;131
      - GROUP=Standard VPN servers
      - RANDOM_TOP=10
      - RECREATE_VPN_CRON=5 */3 * * *
      - NETWORK=192.168.1.0/24;192.168.2.0/24
      - OPENVPN_OPTS=--mute-replay-warnings
    ports:
      - 8080:80
    restart: unless-stopped
  
  web:
    image: nginx
    network_mode: service:vpn

I tried to add the vpn service to my docker-compose and then added network_mode: service:vpn under my consumer1 service but it said something network_mode and link was not able in combination if I do not remember wrong.

Is it possible to do what i want?

Edit: To summarize: I can get the consumers to connect to kafka service but when I try to add NordVPN it seems that I manage to connect the consumer with the NordVPN service but then I can´t manage to establish a connection between that consumer and kafka.

So basically. consumer needs to be able to talk to kafka service but should be on the network for NordVPN so my IP is changed when the consumer makes action on the web.

If I understand well what you want, I don’t think that is possible. ONe VPN connection has one IP address. When you connect to the VPN container, you just reuse its network namespace like the processes of the two containers wer in the same container.

We would need a more specific error message since I don’t see anything in your compose files or commands that could result an error like that. Without seeing your compose file, I would say that you try to use “links” for the same service that you try to connect to an other service’s network namespace. Since containers using an other container’s network namespace have no own network, you can’t link them to an other container. You need to use “links” on the target container which has its own network. In this case the VPN. But your compose files looks right.

You need someone who understands the network more then me, but VPNs often changes the routing so you can’t connect other machines on the local, private network. In this case, the vpn server is in a container which makes it more complicated.

In my opionion (but I am not sure if I am right) you should not use network_mode to use the vpn container’s network namespace, but use the default docker compose networks and try to change the routing from your container or from the host so all traffic goes through the VPN container which forwards it through the VPN connection. There were multiple similar questions on the forum, but I still don’t know the solution since I have never tried anything like this. :frowning: Probably I should

Some minor additions to @rimeleks post:

links is an old relic from ancient times when docker didn’t provide dns-based service disovery. I would suggest to drop it all along.

links generaly does three things: expresses dependency (which you already do using depends_on), adds an entry in /etc/hosts for the linked container name and its allias, and it inherits the environment variable of the linked container. None of those things are usefull in particular: you have dns-based service discovery, you have depends_on to express the dependency and inheriting all environment variables is not desirable as it can leak details into a container you don’t want there.

With network_mode: service:vpn you don’t require service discovery at all, as all containers using it will use the same network namespaceas → localhost will be the same localhost for all of them - this allows a consumer in a container to access a service in another container by using localhost:{containerport}, e.g. if producer and kafka are using teh same network_mode, the producer service can use “localhost:8082” to access kafka. Though, be aware that for containers that use network_mode, there is no way to assign them to further (docker) networks.

Also published ports belong on the service that “owns” the network namespace, which in your case is the vpn service - all others are just share it.