Linking problems between two containers

Hi everyone,

I’m relatively new to Docker (just a week or two). Here’s my problem, which I’ve spent days trying to resolve:

– My first Docker container is running Redis
– My second Docker container is running Tomcat with a custom web app (Java based REST API)
– The web app uses Redis as a data caching layer
– My primary reference for implementing the linking is https://hub.docker.com/_/redis/
– Currently I’m running on Docker for Windows, but the host platform is likely to change in Production

I start the Redis container with
docker run --name myredisserver -d -p 6379:6379 redis redis-server --appendonly yes
(have also tried with various combinations, such as no -p parameter, etc)

I start the Tomcat container with
docker run --name myapi -p 8080:8080 --link myredisserver:redis -d myapiimage
The code uses the Lettuce library and initialises Redis with
RedisClient.create("redis://localhost");

The API (Tomcat) responds fine when calling services that don’t use Redis (e.g. “http://localhost:8080/api/debug” displays the message I expect)
My test service for Redis adds a key/value pair then retrieves it and displays it. When initialising Redis using localhost as above, I get a 500 error:
io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379

After trying everything I could find online, in desperation, I got the value of the Redis container’s IP, and changed localhost to that IP:
RedisClient.create("redis://172.17.0.2");
Then rebuilt and redeployed.

This time it worked as expected. That made it pretty clear what the problem was, but I thought the purpose of the --link parameter was so that it would take care of network communication between the two containers. Also that the -p param on the Redis container would expose port 6379 to localhost. What am I missing?

What’s the best practice for achieving this (what should be quite basic) communication, especially when you don’t know what the final IPs of the two containers will be, or whether they’ll be on different hosts, or clustered (swarmed?), etc.?

Thanks for your help!
James

Connecting containers using links is not advisable, this will be deprecated soon. Inside Tomcat, are you expecting redis://localhost to resolve to redis container ip address?
You can also try changing this from:
RedisClient.create("redis://localhost");
to
RedisClient.create("redis://redis");
Docker post 1.9 version has service discovery built-in. As long as you put 2 containers in the same network, you can reach other container by name.
The same applies for Docker swarm. When you create services and put them in same network, services will be accessible by service name.

Regards
Sreenivas

Hi Sreenivas,

Thanks for the news on the upcoming deprecation.

Yes, my expectation was that the --link parameter would effectively make the container accessible through localhost, and that you only needed to consider the port.

I’ve tried your suggestion to use ‘redis’ as the hostname in the client creation, but it gave a similar error (Unable to connect to redis:6379). I also tried using the container name ‘myredisserver’… Error: Unable to connect to myredisserver:6379. So clearly I need to look at another approach.

Obviously I can start Redis, check its IP, then pass that as a parameter into the Tomcat container, but I’d like an approach that’s less hands-on (more automatic). Are any of these options possible?:

– Explicitly set the container IPs at start up time. Not ideal, but I could work with it in the short term.
– Give each container a hostname at startup. If this is an option, is a DNS server or host file addition required? Or does Docker provide its own hostname resolution layer?

Are there any other ways I could get this working?

Thanks again,
James

With the link feature you have used above, you should be able to access “redis” from “tomcat” container. I am not sure what is going wrong.
Can you try this:
Do a “docker exec” to “tomcat” container and “cat /etc/hosts”. You should see a mapping between redis to the ip address of redis container. Also, you can try pinging to redis container. This would prove that linking is working fine.

You can do service discovery without linking.
Following is an example of wordpress to mysql with linking:
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=“mysql” mysql
docker run --name mywordpress -p 8081:80 --link mysql:mysql -d wordpress

The same example above can be done as below using proper service discovery:
docker network create backend
docker run -d --name mysql --network backend -e MYSQL_ROOT_PASSWORD=“mysql” mysql
docker run --name mywordpress -p 8081:80 --network backend -e WORDPRESS_DB_PASSWORD=“mysql” -d wordpress

This is the new preferred approach.

If you are interested in other Docker networking tips, I captured some of them here(https://www.slideshare.net/SreenivasMakam/docker-networking-common-issues-and-troubleshooting-techniques)

Regards
Sreenivas

Hosts content and ping output is below. No luck with pinging redis by IP. I noticed something strange… “127.0.0.localhost” in both containers. Is that normal? In the meantime, I’ll try the other approach.

Regards,
James

docker exec myapi cat /etc/hosts
127.0.0.localhost ip6-localhost ip6-loopback
fe00::0 ip6-mcastprefix
ff02::1 ip6-allrouters
172.17.0.3 78a7c22d31e6

docker exec myredis cat /etc/hosts
127.0.0.localhost ip6-localhost ip6-loopback
fe00::0 ip6-mcastprefix
ff02::1 ip6-allrouters
172.17.0.2 2e412fe79e02

ping 172.17.0.2

Pinging 172.17.0.2 with 32 bytes of data:
Reply from 150.101.32.14: Destination net unreachable.
Reply from 150.101.32.14: Destination net unreachable.
Reply from 150.101.32.14: Destination net unreachable.
Reply from 150.101.32.14: Destination net unreachable.

Ping statistics for 172.17.0.2:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),

I seem to be having the same issue as this: IP address given to container is not routable in bridge mode
Except that I’m using Docker for Windows.

The other container can ping 172.17.0.2, but the host cannot.
No form of host name in the ping seems to work from the other container though:

docker exec myapi ping myredis
ping: unknown host

docker exec myapi ping redis
ping: unknown host

docker exec myapi ping 2e412fe79e02
ping: unknown host

I see that the linking itself has not worked. In the /etc/hosts output of myapi container, I dont see redis, thats why you are not able to reach by name I am not sure if the linking functionality is supported in Windows. I tried to search this topic, but the results were not conclusive. Can you pls try the other approach that i mentioned, that should work.