I try to connect from backend container to postgres container.
Here is my docker-compose file:
version: "3.9"
services:
imgress-producer:
build:
context: ./producer
dockerfile: Dockerfile.producer
target: prod
container_name: imgress-producer
ports:
- 8080:8080
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- DATABASE_HOST=${DATABASE_HOST}
- DATABASE_PORT=${DATABASE_PORT}
depends_on:
- imgress-db
volumes:
- ./:/app
networks:
- imgress-network
imgress-db:
image: postgres
container_name: imgress-db
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- DATABASE_HOST=${DATABASE_HOST}
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- 5432:5432
networks:
- imgress-network
restart: always
volumes:
postgres-data:
networks:
imgress-network:
driver: bridge
The .env file:
POSTGRES_USER=postgres
POSTGRES_PASSWORD=root
POSTGRES_DB=imgress
DATABASE_HOST=imgress-db
DATABASE_PORT=5432
And here is how I try to connect to db:
package database
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var GDB *gorm.DB
func ConnectDB() {
var err error
pgPort := os.Getenv("DATABASE_PORT")
pgHost := os.Getenv("DATABASE_HOST")
pgUser := os.Getenv("POSTGRES_USER")
pgPassword := os.Getenv("POSTGRES_PASSWORD")
pgName := os.Getenv("POSTGRES_DB")
configData := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=disable",
pgUser,
pgPassword,
pgHost,
pgPort,
pgName,
)
for i := 0; i < 5; i++ {
GDB, err = gorm.Open(postgres.Open(configData), &gorm.Config{})
if err == nil {
break
}
time.Sleep(10 * time.Second)
}
if err != nil {
log.Println("Producer: Error Connecting to Database")
} else {
log.Println("Producer: Connection Opened to Database")
}
}
So, in the last part, I retry until db container is ready. So it should log an error when db connection is unsuccessful. But instead, it fails to connect and logs a success.
imgress-producer | 2022/12/03 20:28:24 /go/pkg/mod/gorm.io/[email protected]/gorm.go:206
imgress-producer | [error] failed to initialize database, got error failed to connect to `host=imgress-db user=postgres database=imgress`: dial error (dial tcp 172.23.0.3:5432: connect: connection refused)
imgress-producer | 2022/12/03 20:28:34 Producer: Connection Opened to Database
There is a lot of connection refused related questions asked on SO, but none of them helped me. So any kind of help is appreciated.
2
Answers
I simplified your code a little bit and I was able to make it work on my machine. Let’s see it. The repo structure is:
.env
docker-compose.yaml
Dockerfile
main.go
Let’s start with the
main.go
file.main.go
No relevant changes here.
.env
Also here nothing to mention.
Dockerfile
Here we used the multi-staged build to build and copy our Go program. In the
build
stage we used a bigger image to initialize a go module, restore the dependencies and, to build the source code. While in the leaner image we copy the outcome of our build process.docker-compose.yaml
For the sake of the demo, I’ll leave out the volumes. It shouldn’t big a pain to integrate also them too.
Hope that this clarifies a little bit your doubt!
A workaround solution.
if you looked here I bet you have been through a log of "changing hostname from localhost to DB". None of that worked for me. I have gone through every documentation for the docker-compose network but it just does not work. Here is the solution
this will expose your DB to the host machine network and your app will connect to your DB through the host machine. No very ideal, but the best solution found so far. If anyone has a real solution and has tried it yourself. Please let me know.