7

I tried linking a container running a spring boot 2 app to a container running mongo, but I get connection refused

docker-compose file to have a container for mongo (will later add another container for spring boot here as well)

version: '3.1'

services:
  mongo:
    image: mongo
    container_name: springboot-mongo
    ports:
      - 27017:27017
    volumes:
      - $HOME/data/springboot-mongo-data:/data/db
      - $HOME/data/springboot-mongo-bkp:/data/bkp
    restart: always

dockerfile for spring boot

FROM openjdk:11
RUN apt-get update && apt-get install bash
RUN mkdir -p /opt/app
ENV PROJECT_HOME /opt/app
COPY build/libs/recipe-book.jar $PROJECT_HOME/recipe-book.jar
WORKDIR $PROJECT_HOME
CMD ["java", "-Dspring.data.mongodb.uri=mongodb://springboot-mongo:27017/recipes", "-jar","./recipe-book.jar"]

i have tried different ways of sending the command line mongo uri: with localhost instead of springboot-mongo, i also tried how it is described here https://www.baeldung.com/spring-boot-command-line-arguments, more specifically -Dspring-boot.run.arguments=--spring.data.mongodb.uri=mongodb://springboot-mongo:27017/recipes. Every time it seems to hit a connection refused.

How can I make the spring container connect to mongo?

Thank you

Update, I have also tried adding the second container to the docker-compose file, as such

version: '3.1'

services:
  springboot:
    build: .
    restart: always
    container_name: springboot
    ports:
      - 8182:8080
    working_dir: /opt/app
    depends_on:
      - mongo

  mongo:
    image: mongo
    container_name: springboot-mongo
    ports:
      - 27017:27017
    volumes:
      - $HOME/data/springboot-mongo-data:/data/db
      - $HOME/data/springboot-mongo-bkp:/data/bkp
    restart: always

update 2:

I managed so partially solve the issue by first building the image locally on my computer, and then using the created image inside the docker-compose file, and having -Dspring.data.mongodb.uri=mongodb://springboot-mongo:27017/recipes as parameter, but still no luck building it directly in the docker-compose file

Claudiu Guja
  • 290
  • 1
  • 3
  • 12
  • have you tried `CMD ["java", "-Dspring.data.mongodb.uri=mongodb://mongo:27017/recipes", "-jar","./recipe-book.jar"]` ? (replacing springboot-mongo by mongo) – Abdelkarim EL AMEL Apr 14 '19 at 10:10
  • How are you running the second container? Are you adding it to the `docker-compose.yml` file, or separately running `docker run`? Does `mongo` (the name of the `services:` block) work? – David Maze Apr 14 '19 at 10:48
  • you must add the otherone to the docker-compose file to get its name resolved in the other one – Efrat Levitan Apr 14 '19 at 13:02
  • I have tried replacing springboot-mongo with just mongo, it did not work. I was calling the second container with `docker run`. I tried adding the second container to the docker-compose file, it also did not seem to have any effect – Claudiu Guja Apr 14 '19 at 14:12
  • @DavidMaze, if i try`mongo localhost:27017` it works, but not `mongo springboot-mongo:27017` – Claudiu Guja Apr 14 '19 at 14:24
  • Does the springboot app retry to give mongo time to start? Have you verified mongo is running? – BMitch Apr 14 '19 at 15:09
  • when starting with `docker-compose up` it always says the mongo container is done before even starting the spring container – Claudiu Guja Apr 14 '19 at 15:26

5 Answers5

5

If you want two containers to talk to each other then you need to put them in the same docker network

update your docker-compose.yml file like this:

version: '3.1'
services:
  springboot:
    build: .
    restart: always
    container_name: springboot
    ports:
      - 8182:8080
    working_dir: /opt/app
    depends_on:
      - mongo
    networks:
      - local

  mongo:
    image: mongo
    container_name: springboot-mongo
    ports:
      - 27017:27017
    volumes:
      - $HOME/data/springboot-mongo-data:/data/db
      - $HOME/data/springboot-mongo-bkp:/data/bkp
    restart: always
    networks:
      - local
networks:
  local:
    driver: bridge
Tea Curran
  • 2,923
  • 2
  • 18
  • 22
shushu304
  • 1,506
  • 1
  • 7
  • 15
  • And indeed it works. Will need to look further into how docker and its networking works though. Thank you very much – Claudiu Guja Apr 14 '19 at 21:07
  • 1
    There's no need to specify a network with v2 and v3 of the compose file syntax. Both docker-compose and swarm mode create a default network for the project/stack of you do not specify one. If you try to run the same compose file in swarm mode, it will break trying to communicate across multiple nodes since the default overlay network that would be created is disabled. – BMitch Apr 15 '19 at 08:49
  • 41
    I have the same network for all containers, but still I get "connection refused" – osynavets Dec 21 '19 at 21:03
  • @osynavets you found the cause? I have same issue – hldev Apr 10 '22 at 19:07
  • 5
    @hldev it was two years ago, I don't remember a thing. But I can say that if you use docker network you should specify docker service name (not container name) as a host name in your connection or whatever you have. In this case that would be 'mongo' and not localhost. – osynavets Apr 11 '22 at 06:32
5

You don't really need to use docker-compose.

Let's work step by step:

Create a network, like:

docker network create network-labolida

Start two container with:

docker run --hostname=www1 -p 81:8080  --net=network-labolida --name=www1  -t www1 
docker run --hostname=www2 -p 82:8080  --net=network-labolida --name=www2  -t www2 

Validate it:

docker network inspect network-labolida

This is going to tell you the container names associated to that network.

Then, the trick: USE THE CONTAINER NAMES!

DON'T USE EXPOSED PORTS but INTERNAL ONES: 8080!

I mean:

If you want to access your contained-services from your HOST, using PostMan for example, use:

http://127.0.0.1:81/api/mymicroservice/

http://127.0.0.1:89/api/mymicroservice/

BUT

If, what you want is to make your container-01 access the contanier-02 , then use:

http://www2:8080/api/mymicroservice/

(HOSTNAME+InternalPort) from the container-01.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
0

If you are

  • getting Connection refused while trying to communicate between two containers
  • trying to communicate between two containers from different docker-compose projects and don't want to use the same network (because let's say they would have PostgreSQL or Redis container on the same port and you would prefer to not changing these ports and not use it at the same network)
  • developing locally and want to imitate communication between two docker compose projects
  • running two docker-compose projects on localhost
  • developing especially Django apps or Django Rest Framework (drf) API and running app inside container on some exposed port

And you want to

  • container api_a communicate to api_b (or vice versa) without the same "docker network"

(example below)

you can use "host" of the second container as IP of your computer and port that is mapped from inside Docker container. You can obtain IP of your computer with this script (from: Finding local IP addresses using Python's stdlib):

import socket
def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

Example:

project_api_a/docker-compose.yml:

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_a
    image: api_a:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

inside api_a container you are running Django app: manage.py runserver 0.0.0.0:8000

and second docker-compose.yml from other project:

project_api_b/docker-compose-yml :

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_b
    image: api_b:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

inside api_b container you are running Django app: manage.py runserver 0.0.0.0:8001

And trying to connect from container api_a to api_b then URL of api_b container will be: http://<get_ip_from_script_above>:8001/

It can be especially valuable if you are using even more than two(three or more) docker-compose projects and it's hard to provide common network for all of it - it's good workaround and solution

Rafał
  • 572
  • 4
  • 21
-1

If you a re using reference to localhost inside container, use --network="host" when run docker.

Alexander
  • 127
  • 2
  • 10
-1

In addition to @shushu304's answer, this worked for me for containers with problems

networks:
  - local
  - default