skip to Main Content

When I run docker-compose up postgres service start successful. However my Golang API can not connect to my postgres service. I tried manually without docker and it works. Golang Connection string looks like this host=db port=5432 user=%s dbname=%s password=%s sslmode=disable. But when I restart my container, it works.

docker-compose

    FROM golang:1.22
    WORKDIR /app
    COPY . .
    RUN go install

Dockerfile

    version: "3.7"
    services:
      gobank:
        build: .
        container_name: gobank
        env_file:
          - .env
        ports:
          - 3000:3000
        command: make run
        extra_hosts:
          - "host.docker.internal:host-gateway"
    
      db:
        image: postgres:16
        container_name: postgres
        environment:
          - POSTGRES_PASSWORD=postgres
          - POSTGRES_USER=postgres
          - POSTGRES_DB=gobank
        ports:
          - 5432:5432
        extra_hosts:
          - "host.docker.internal:host-gateway"
PostgresLog
    postgres  | 2024-07-12 22:51:24.133 UTC [1] LOG:  starting PostgreSQL 16.3 (Debian 16.3-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
    postgres  | 2024-07-12 22:51:24.133 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
    postgres  | 2024-07-12 22:51:24.133 UTC [1] LOG:  listening on IPv6 address "::", port 5432
    postgres  | 2024-07-12 22:51:24.135 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
    postgres  | 2024-07-12 22:51:24.138 UTC [64] LOG:  database system was shut down at 2024-07-12 22:51:24 UTC
GolangLog
    gobank    | 2024/07/12 22:51:23 there was an error: dial tcp 172.18.0.2:5432: connect: connection refused
    gobank    | make: *** [Makefile:14: run] Error 1
    postgres  | performing post-bootstrap initialization ... ok
    gobank exited with code 2
    postgres  | syncing data to disk ... ok

2

Answers


  1. Your Go program tried to connect to the database before it was ready. To make Docker wait until Postgres is ready before starting your Go program, you need to add a healthcheck to the db container, like this:

    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres", "-d", "gobank"]
      interval: 10s
      timeout: 5s
      retries: 10
    

    Then, you need to make the Go program depend on the healthcheck like so:

    depends_on:
      db:
        condition: service_healthy
    
    Login or Signup to reply.
  2. You can add:

    depends_on:
      - db
    

    and as a measure add a health check inside golang in the form of a endless for loop which basically pings the DB.

    go func() {
        for {
            err := cnx.Cnx.Ping()
            if err == nil {
                log.Info("DB Health Check Success")
            } else {
                log.Warn("DB Health Check Failed")
            }
            time.Sleep(time.Hour * 3)
        }
    }()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search