mewais
mewais

Reputation: 1337

Docker compose: services cannot connect to each other

I've been following this tutorial on docker services and swarms. But I'm having some trouble with networking between different docker containers.

The following is my docker-compose.yml file, it basically contains two services. One is just a redis image connected to two networks (although the second is useless for now). And the other is my application which needs to connect to redis. For that reason I opted to give the redis service a static IP.

version: "3"

services:
  my_redis:
    image: redis
    ports:
      - "6379:6379"
    networks:
      first_network:
        ipv4_address: 172.20.1.1
      second_network:
        ipv4_address: 172.30.1.1
  my_app:
    build:
      context: .
      dockerfile: Dockerfile_my_app
    image: my_app_image
    depends_on:
      - my_redis
    deploy:
      replicas: 1 # 4
    networks:
      - first_network

networks:
  first_network:
    ipam:
      config:
        - subnet: 172.20.1.0/24
  second_network:
    ipam:
      config:
        - subnet: 172.30.1.0/24

And the following is my Dockerfile for my_app:

FROM python:3.7
WORKDIR /app
COPY . /app
RUN pip3 install --trusted-host pypi.python.org -r requirements.txt
CMD ip a && wait-for-it.sh 172.20.1.1:6379 && PYTHONPATH=. python3 my_app.py

Now the problem I'm having is that for some reason, my app cannot connect to the redis service. So I tried the following:

  1. I tried running the redis container alone, using the following command: sudo docker run -p 6379:6379 redis and then I used wait-for-it to make sure that localhost:6379 was up and running and it was.
  2. I thought then maybe docker stack deploy is creating the app service before the redis service, So I added the depends_on part in the docker-compose file.
  3. I found out that even depends_on only guarantees order of starting (not being ready, i.e. not running all commands before proceeding to next image) and that I have to find a different solution. Based on that I also changed the Dockerfile_my_app to run wait-for-it before it actually runs my app. Didn't work.
  4. Lastly, I didn't know what else to do, I ran ip a to see if my_app service is getting the right IP. and it is getting an IP in the right range:

    my_test_my_app.1.jydyydckzyfh@snode-01    | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    my_test_my_app.1.jydyydckzyfh@snode-01    |     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    my_test_my_app.1.jydyydckzyfh@snode-01    |     inet 127.0.0.1/8 scope host lo
    my_test_my_app.1.jydyydckzyfh@snode-01    |        valid_lft forever preferred_lft forever
    my_test_my_app.1.jydyydckzyfh@snode-01    | 1010: eth0@if1011: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
    my_test_my_app.1.jydyydckzyfh@snode-01    |     link/ether 02:42:ac:14:01:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    my_test_my_app.1.jydyydckzyfh@snode-01    |     inet 172.20.1.3/24 brd 172.20.1.255 scope global eth0
    my_test_my_app.1.jydyydckzyfh@snode-01    |        valid_lft forever preferred_lft forever
    my_test_my_app.1.jydyydckzyfh@snode-01    | 1012: eth1@if1013: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    my_test_my_app.1.jydyydckzyfh@snode-01    |     link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    my_test_my_app.1.jydyydckzyfh@snode-01    |     inet 172.18.0.3/16 brd 172.18.255.255 scope global eth1
    my_test_my_app.1.jydyydckzyfh@snode-01    |        valid_lft forever preferred_lft forever
    my_test_my_app.1.jydyydckzyfh@snode-01    | wait-for-it.sh: waiting 15 seconds for 172.20.1.1:6379
    my_test_my_app.1.jydyydckzyfh@snode-01    | wait-for-it.sh: timeout occurred after waiting 15 seconds for 172.20.1.1:6379
    

So in short, IPs are getting assigned correctly. However, the my_app service cannot connect to the redis service. Is there any reason why? Am I missing something in the compose file?

Any help would be appreciated.

Upvotes: 4

Views: 3915

Answers (1)

applecider
applecider

Reputation: 303

Try changing wait-for-it.sh 172.20.1.1:6379 in Dockerfile_my_app to:

wait-for-it.sh my_redis:6379

and see if that works.

Explanation: If i'm not wrong, once containers are part of the same network, they are able to communicate with each other via the service names declared in the docker-compose file.

See https://docs.docker.com/compose/compose-file/ under 'Networks' and https://docs.docker.com/compose/networking/ for detailed information

Upvotes: 8

Related Questions