I'm trying to do a zero downtime deploying w/ docker-compose and traefik, but I'm having issues with a container cross communicating with another project.
docker-compose.yml (details omitted)
services:
proxy:
networks:
- net
app:
networks:
- net
auth:
networks:
- net
networks:
net:
external:
name: traefik_webgateway # not really important here
I run two different instances of my services via:
docker-compose --env-file=.env --project-name=green -f docker-compose.yml up
docker-compose --env-file=.env --project-name=blue -f docker-compose.yml up
My services in "green" work fine until I run the "blue" project. When "blue" is being brought up, some of the requests in the "green" "proxy" container is being routed to the "blue" container. Example call being made in "proxy" to talk to the "auth" service:
http://auth/session
I need the networking in "green" to stay in "green", and "blue" in "blue"... otherwise some of the requests in "green" is going to "blue" when it isn't ready it causing API failures. Once all the containers are ready, everything works but this isn't zero downtime.
It looks like everything is bound by the container name. I don't want to use container_name
because I want to use the docker scale
.
My workaround is creating docker-compose.blue.yml
and docker-compose.green.yml
and duplicates everything but suffix the container name
with _blue
and _green
. But I'm wondering if there's a better solution.
Thanks in advance.
EDIT: The proposed solution answers the question, but by adding the internal
network to my proxy
, traefik loses communication with my service.
By default, docker-compose
will setup a single, isolated network for your project. When using custom networks those, too, will be namespaced with the project name, isolating projects with different names - see the docker-compose
networking docs.
BUT: in your example all the containers are connected to an external network which is not namespaced and thus is the same even for different projects. Since the container also share the same name resolving them in that network may result in either the green or blue version.
There are several ways to solve this. The appropriate method depends on your particular use case. The best and also the safest method would be to isolate all containers with the same project name to their own internal network and only expose the ports intended for outside connection into the external network:
services:
proxy:
networks:
- net
- internal
app:
networks:
- internal
auth:
networks:
- internal
networks:
internal:
net:
external:
name: traefik_webgateway # not really important here
Here, all the containers are only connected to a project-scoped, internal network and are able to communicate with each other. Only the proxy
service is also connected to the external net
network and can be connected to from there.
If you really need to connect all services to the same external network, you could use aliases
together with variable substitution:
services:
proxy:
networks:
net:
aliases:
- proxy_${COLOR}
app:
networks:
net:
aliases:
- app_${COLOR}
auth:
networks:
net:
aliases:
- auth_${COLOR}
networks:
net:
external:
name: traefik_webgateway # not really important here
This is basically your workaround but with a single docker-compose.yml
which you can use like this:
COLOR=green docker-compose --env-file=.env --project-name=green -f docker-compose.yml up
COLOR=blue docker-compose --env-file=.env --project-name=blue -f docker-compose.yml up