1
votes

Let's say I defined two services "frontend" and "db" in my docker-compose.yml which are deployed to a Docker swarm, i.e. they may also run in different stacks. With this setup Traefik automatically generates the frontend and backend for each stack which is fine.

Now I have another Docker container running temporarily in a Jenkins pipeline which shall be able to access the db service in a specific stack. My first idea was to expose the db service by adding it to the cluster-global-net network so that Traefik can generate a frontend route to the bakend. This basically works.

But I'd like to hide the database service from "the public" while still being able to connect another Docker container to it via its stack or service name using the internal "default" network.

Can this be done somehow?

version: '3.6'

networks:
  default: {}
  cluster-global-net:
    external: true

services:
  frontend:
    image: frontend_image
    ports:
    - 8080
    networks:
    - cluster-global-net
    - default
    deploy:
      labels:
        traefik.port: 8080
        traefik.docker.network: cluster-global-net
        traefik.backend.loadbalancer.swarm: 'true'
        traefik.backend.loadbalancer.stickiness: 'true'
      replicas: 1
      restart_policy:
        condition: any

  db:
    image: db_image
    environment:
    - MYSQL_ALLOW_EMPTY_PASSWORD=false
    - MYSQL_DATABASE=db_schema
    - MYSQL_USER=db_user
    - MYSQL_PASSWORD=db_pass
    ports:
    - 3306
    volumes:
    - db_volume:/var/lib/mysql
    networks: 
    - default
    restart: on-failure
    deploy:
      labels:
        traefik.port: 3306
        traefik.docker.network: default
1

1 Answers

2
votes

What you need is a network on which both of them are deployed, but that it's not visible from anyone else.

To do such, create a network , add it to your db service and frontend, and also to your temporary service. And indeed, remove traefik label on db because they are not needed anymore here.

EG :

...
networks:
  default: {}
  cluster-global-net:
    external: true
  db-net:
    external: true

services:
  frontend:
    image: frontend_image
    networks:
    - cluster-global-net
    - default
    - db-net
    deploy:
        ...

  db:
    image: db_image
    ...
    networks: 
    - default
    - db-net
    restart: on-failure
    #no labels


docker network create db-net 
docker stack deploy -c <mycompose.yml> <myfront>
docker service create --network db-net <myTemporaryImage> <temporaryService>

Then, the temporaryService as well as the frontend can reach the db through db:3306

BTW : you don't need to open the port for the frontend, since traefik will access it internally (trafik.port).

EDIT : new exemple with network created from compose file.

...
networks:
  default: {}
  cluster-global-net:
    external: true
  db-net: {}

services:
  frontend:
    image: frontend_image
    networks:
    - cluster-global-net
    - default
    - db-net
    deploy:
        ...

  db:
    image: db_image
    ...
    networks: 
    - default
    - db-net
    restart: on-failure
    #no labels


docker stack deploy -c <mycompose.yml> someStackName
docker service create --network someStackName_db-net <myTemporaryImage> <temporaryService>