When container is started with the same name it fails to relink

Suppose we have three containers named frontend, backend-1 and backend-2. frontend has a link to backend-1 with the flag --link backend-1:backend
We remove frontend container.
Then we run frontend again but link it with backend-2
Linking fails. There are no errors, but container frontend has no way of contacting backend-2

This happens both on
Windows 8, Docker version 1.11.1
CentOS Linux release 7.2.1511 (Core), Docker version 1.11.1

Expected:
command
docker run -d --name frontend --link backend-2:backend redis
should link backend-2 to frontend

The next script shows the problem (I can’t upload anything for now, so I just copy the code here):
#!/bin/bash echo Run three containers - two backends and one frontend linked to backend-1 docker run -d --name backend-1 redis docker run -d --name backend-2 redis docker run -d --name frontend --link backend-1:backend redis echo echo These are hosts in frontend linked with backend-1, you can see it in hosts docker exec frontend cat /etc/hosts echo echo Stop and remove frontend and restart it with linking to backend-2 docker rm $(docker stop frontend) docker run -d --name frontend --link backend-2:backend redis echo echo These are hosts in frontend linked with backend-2, but you cannot see entry in hosts docker exec frontend cat /etc/hosts echo echo Just for test: run another container with the same command, just with the different name and check its hosts to see that backend-2 is there docker run -d --name frontend-2 --link backend-2:backend redis echo docker exec frontend-2 cat /etc/hosts echo echo Stop frontend and backend-1, that it was previously linked to docker rm $(docker stop frontend) docker rm $(docker stop backend-1) echo Start frontend again with link to backend-2 docker run -d --name frontend --link backend-2:backend redis echo echo These are hosts in frontend linked with backend-2 and you can see the entry in hosts now: docker exec frontend cat /etc/hosts echo echo Clean all running containers docker rm $(docker stop frontend frontend-2 backend-2)

Links are fairly well deprecated by now and have a variety of issues. Try the “proper” way with docker networks, e.g.:

$ docker network create mynet
f1d39e014d1ad1789b4daec5e23097949a794f0999a7ee664d93cc2de84ce5ec

$ docker run -d --net mynet --name listener alpine nc -l -p 8080
ad02d8fc27548a1ed88d1f68a391d32fb96463c103aa2740a13f7d65da32fc39

$ docker run --net mynet alpine sh -c 'echo hello anyone listening | nc listener 8080'

$ docker logs listener
hello anyone listening

It will allow you to restart one container without needing to manage the other one IIRC.

1 Like

Thank you for reply, I did try the “network” way but this approach does not work in our environment.
So this is the simplified real usecase:
We have backend and frontend. Then we start develop new feature and start with frontend, we deploy new frontend container with the name frontend-new, which still looks at the old backend. Now we change the backend and deploy the new backend with the container name backend-new. We want to relink fronend-new to the backend-new.
With links we would just restart the frontend container with --link backend-new:backend.

With networks it is not possible. We don’t want to call containers by name because there can be several backends and we want to specify which backend should be used only when we execute “docker run” command.
On the other side we can’t put these new backends and frontends in the separate network, because there is a time when new frontend still looks at the old backend. [EDIT: containers should have unique names per machine, not per network, so this approach wouldn’t work anyway]

The real setup is much more complicated as there can be several branches running at the same time and there are several microservices which are linked to each other.

How can we approach this problem?

I’d use docker-compose for this. Links are still a thing there (implemented, I suspect, using Docker networks underneath). You’d then just need to change the image references that each service uses when you what to upgrade one.

Example docker-compose.yml:

version '2'

services:
    frontend:
        image: frontend-new
        links:
        - backend
  
    backend:
        image: backend; 

So when you’re ready to upgrade the backend, just change the backend image setting.

At first we used docker compose, but then we stopped doing that and moved to the simple “docker run”. There were two main reasons:
First, there can be several branches for frontend (4-5 let’s say) and creating a separate backend for each of them can be a waste of space if they are the same.
Second - backend itself has another dependencies so chain of services can become pretty long. Since we want services to be quite independent and know only about their own dependencies, setting up everything with the docker compose does not work for us.

I’ll have a look whether docker-compose can offer us something similar to --link (for example external-link), but I’m afraid that it will use the --link in the background anyway.

Finally we made linking working. Solution was quite simple:

We created the custom network with
docker network create default-network

and then used it like this:
docker run --name frontend --net=default-network --link old-backend:backend

–link flag has different meaning in default network and in custom networks and it apparently works correctly in the custom networks.

@mavenugo Can you please take a look at this ? I think similar result can be accomplished without using --link.