尝试连接到MongoDB容器时,GOLANG客户端Docker容器变得无法访问

问题描述:

I have a simple program written in golang which connect to a mongodb instance thus:

func main() {
    session, err := mgo.Dial("localhost:27017")    

    if err != nil {
        panic(err)
    }

    defer session.Close()
    session.SetMode(mgo.Monotonic, true)
    ensureIndex(session)
}

I use docker compose to spin up two containers one to spin up my GOLANG API and the other to spin up mongo:

version: "3.3"

services:
  api:
    image: golang:latest
    volumes:
      - .:/go
    working_dir: /go
    environment:
      - GOPATH=/go
    command:
      go run /go/src/main.go
    ports:
      - "8082:8000"
    depends_on: 
      - db
    networks:
      - api-net    

  db:
    build: .
    expose:
      - '27017'
    container_name: 'mongo'
    ports:
      - "27017:27017"
    networks:
      - api-net

networks:
  api-net:
    driver: bridge

I use a Dockerfile in order to spin up mongo with a conf file that sets the instance to bind to all IPV4 and IPV6 networks:

FROM mongo:latest

COPY mongod.conf /etc/mongod.conf
CMD mongod --config /etc/mongod.conf##

and this is the mongod.conf file:

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0

When I run docker-compose.up this is what I get:

Building db
Step 1/3 : FROM mongo:latest
 ---> a0f922b3f0a1
Step 2/3 : COPY mongod.conf /etc/mongod.conf
 ---> Using cache
 ---> f270e718c11e
Step 3/3 : CMD mongod --config /etc/mongod.conf
 ---> Running in 89ffc2495a2a
Removing intermediate container 89ffc2495a2a
 ---> fe2677d53122

Successfully built fe2677d53122
Successfully tagged carsupermarket_db:latest
WARNING: Image for service db was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating mongo ... done
Creating carsupermarket_api_1 ... done
Attaching to mongo, carsupermarket_api_1
api_1  | panic: no reachable servers
api_1  |
api_1  | goroutine 1 [running]:
api_1  | main.main()
api_1  |        /go/src/main.go:38 +0x291
api_1  | exit status 2

I've trawled Google and * and the only thing I could manage to find which is vaguely related to my issue is:

mongod --bind_ip using docker-compose version 2

however, my docker-compose.yml file as it stands 'Should' on paper work.

Can someone please point me in the correct direction as to why my GOLANG code cannot find my mongodb instance.

I think that when you call mgo.Dial("localhost:27017") the localhost part refers to the localhost within the golang container, and not the host the the containers are running on.

Docker will resolved container names as host names, change the dial to mgo.Dial("mongo:27017") and it should work.

From the docker container networking bridge docs

User-defined bridges provide automatic DNS resolution between containers.

Containers on the default bridge network can only access each other by IP addresses, unless you use the --link option, which is considered legacy. On a user-defined bridge network, containers can resolve each other by name or alias.

https://docs.docker.com/network/bridge/

version: "2"

services:
  api:
    image: golang:latest
    volumes:
      - .:/go
    # Work dir should be defined in dockerfile
    #working_dir: /go
    environment:
      - GOPATH=/go
    command:
      go run /go/src/main.go
    ports:
      - "8082:8000"
    depends_on: 
      - db 

  db:
    build: .
    container_name: 'mongo'
    # You should define some volumes here if you want the data to persist.

You should be able to connect from the golang container to the mongo container using inter container communication using the hostname: 'mongo'