Routing between stacks #
Sometimes you need to use an internal network to access services which run in other stacks. A reason would include to have individual deployments of services and to reduce the blast radius when things don’t work out as expected.
By default (or implicitly), all services in a stack are in a network called default (stack-default
). This is how services can talk to each other when defined in the same stack and without defining explicit networks.
This implies that services in one stack may not necessary see services in other stacks.
Example #
In order for the routing across stacks to work, you should create a new docker network on the Quantum Console (select your cluster/endpoint, Networks » Add Network). Make sure it’s of type overlay
and for good measure make it attachable
(in order to be able to attach not just Swarm services but also individual containers).
In the following example, we assume you create a network called global-lan
.
Then, let’s add a new backend
stack and make sure the services are attached to global-lan
:
# "backend" stack
version: "3.8"
services:
api:
image: foo/bar
environment:
DSN: mysql://user:pass@tasks.db:3306/db
networks:
- backend
- lan
db:
image: mariadb/server
networks:
- backend
networks:
backend:
lan:
name: global-lan
external: true
The `tasks.service` host is based on the internal DNS on Docker Swarm. It's not available in client-side (JavaScript) applications. The beauty of these hosts is that a Swarm service can be one or more containers. This DNS will pick one and you don't have to remember IP addresses or setup IPAM on the network.
Then, let’s add a frontend stack โ this assumes Traefik, but it works with Caddy as well:
# "frontend" stack
version: "3.8"
services:
frontend-service:
image: foo/bar
deploy:
labels:
traefik.enable: true
traefik.frontend.rule: Host:example.org
traefik.docker.network: public
environment:
API_SERVICE: "http://tasks.api:8080"
networks:
- lan
- public
networks:
lan:
name: global-lan
external: true
public:
external: true
How does it work? #
These are the rules that we created due our new network:
- Traefik 👉
frontend-service
: ✅ - Traefik 👉
db
: ❌ no access - Traefik 👉
api
: ❌ no access frontend-service
👉api
: ✅frontend-service
👉db
: ❌ no accessapi
->db
: ✅
In summary #
The backend
stack is completely sealed off from the public Internet.
All services connected to `global-lan` **need unique names** in order for DNS resolution (`tasks.SERVICE-NAME`) to work. So make sure to double-check. The same constraint is true for the `public` network to work as well.
Further reading: