Home > database >  Postgres Go Docker-compose Can't ping database: dial tcp 127.0.0.1:5432: connect: connectio
Postgres Go Docker-compose Can't ping database: dial tcp 127.0.0.1:5432: connect: connectio

Time:11-10

It is not my golang script, but i should to use them in this task: package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
    "log"
    "net/http"

    "github.com/caarlos0/env"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

type config struct {
    PostgresUri   string `env:"POSTGRES_URI" envDefault:"postgres://root:[email protected]/postgres"`
    ListenAddress string `env:"LISTEN_ADDRESS" envDefault:":5432"`
}

var (
    db          *sql.DB
    errorsCount = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "gocalc_errors_count",
            Help: "Gocalc Errors Count Per Type",
        },
        []string{"type"},
    )

    requestsCount = prometheus.NewCounter(
        prometheus.CounterOpts{
            Name: "gocalc_requests_count",
            Help: "Gocalc Requests Count",
        })
)

func main() {
    var err error

    // Initing prometheus
    prometheus.MustRegister(errorsCount)
    prometheus.MustRegister(requestsCount)

    // Getting env
    cfg := config{}
    if err = env.Parse(&cfg); err != nil {
        fmt.Printf("% v\n", err)
    }

    // Connecting to database
    db, err = sql.Open("postgres", cfg.PostgresUri)
    if err != nil {
        log.Fatalf("Can't connect to postgresql: %v", err)
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        log.Fatalf("Can't ping database: %v", err)
    }

    http.HandleFunc("/", handler)
    http.Handle("/metrics", promhttp.Handler())
    log.Fatal(http.ListenAndServe(cfg.ListenAddress, nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
    requestsCount.Inc()

    keys, ok := r.URL.Query()["q"]
    if !ok || len(keys[0]) < 1 {
        errorsCount.WithLabelValues("missing").Inc()
        log.Println("Url Param 'q' is missing")
        http.Error(w, "Bad Request", 400)
        return
    }
    q := keys[0]
    log.Println("Got query: ", q)

    var result string
    sqlStatement := fmt.Sprintf("SELECT (%s)::numeric", q)
    row := db.QueryRow(sqlStatement)
    err := row.Scan(&result)

    if err != nil {
        log.Println("Error from db: %s", err)
        errorsCount.WithLabelValues("db").Inc()
        http.Error(w, "Internal Server Error", 500)
        return
    }

    fmt.Fprintf(w, "query %s; result %s", q, result)
}

It is my docker-compose:

version: "3"
services:
  db:
    image: postgres:10
    environment:
      - POSTGRES_PASSWORD=pass
      - POSTGRES_USER=root
    expose:
      - 5432
    
  backend:
    image: dkr-14-gocalc:latest
    environment:
      - POSTGRES_URI=postgres://root:pass@db/postgres
      - LISTEN_ADDRESS=7000
    depends_on:
      - postgres
  proxy:
    image: nginx
    volumes:
      - type: bind
        source: ./nginx.conf
        target: /etc/nginx/conf.d/default.conf
    ports:
      - 8000:80
    depends_on: 
      - backend

And it is dkr14-gocalc image:

FROM golang:1.19.1-alpine AS builder
ENV GO111MODULE=auto
WORKDIR /go/src/

RUN apk add --no-cache git 
COPY main.go ./
 
#init is initializing and writting new go.mod in current dir.
RUN go mod init main.go

RUN go get -d -v github.com/caarlos0/env \
    && go get -d -v github.com/prometheus/client_golang/prometheus \
    && go get -d -v github.com/prometheus/client_golang/prometheus/promhttp \
    && go get -d -v github.com/lib/pq \   
    && go get -d -v database/sql \
    && go get -d -v fmt \
    && go get -d -v log \
    && go get -d -v net/http
    
RUN go build -o app .

FROM alpine:3.10.3
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/app ./
CMD ["./app"]

I should to make docker compose environment with 3 services GO POSTGRES NGINX. The main idea of task is to learn about environment. Database should have password and golalc should to connect to this database. But what have i done incorrect?

It is my log:

backend_1   | 2022/11/07 23:27:33 Can't ping database: dial tcp 127.0.0.1:5432: connect: connection refused
postgres_1  | The files belonging to this database system will be owned by user "postgres".
postgres_1  | This user must also own the server process.
postgres_1  | 
proxy_1     | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
proxy_1     | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
postgres_1  | The database cluster will be initialized with locale "en_US.utf8".
postgres_1  | The default database encoding has accordingly been set to "UTF8".
postgres_1  | The default text search configuration will be set to "english".
postgres_1  | 
postgres_1  | Data page checksums are disabled.
proxy_1     | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
proxy_1     | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
postgres_1  | 
task14_backend_1 exited with code 1
proxy_1     | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
postgres_1  | fixing permissions on existing directory /var/lib/postgresql/data ... ok
postgres_1  | creating subdirectories ... ok
proxy_1     | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
postgres_1  | selecting default max_connections ... 100
proxy_1     | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
postgres_1  | selecting default shared_buffers ... 128MB
postgres_1  | selecting default timezone ... Etc/UTC
postgres_1  | selecting dynamic shared memory implementation ... posix
proxy_1     | /docker-entrypoint.sh: Configuration complete; ready for start up
postgres_1  | creating configuration files ... ok
postgres_1  | running bootstrap script ... ok
postgres_1  | performing post-bootstrap initialization ... ok
postgres_1  | syncing data to disk ... ok
postgres_1  | 
postgres_1  | Success. You can now start the database server using:
postgres_1  | 
postgres_1  |     pg_ctl -D /var/lib/postgresql/data -l logfile start
postgres_1  | 
postgres_1  | 
postgres_1  | WARNING: enabling "trust" authentication for local connections
postgres_1  | You can change this by editing pg_hba.conf or using the option -A, or
postgres_1  | --auth-local and --auth-host, the next time you run initdb.
proxy_1     | 2022/11/07 23:27:33 [emerg] 1#1: host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
proxy_1     | nginx: [emerg] host not found in upstream "backend" in /etc/nginx/conf.d/default.conf:5
postgres_1  | waiting for server to start....2022-11-07 23:27:33.704 UTC [48] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres_1  | 2022-11-07 23:27:33.722 UTC [49] LOG:  database system was shut down at 2022-11-07 23:27:33 UTC
postgres_1  | 2022-11-07 23:27:33.729 UTC [48] LOG:  database system is ready to accept connections
postgres_1  |  done
postgres_1  | server started
task14_proxy_1 exited with code 1
postgres_1  | CREATE DATABASE
postgres_1  | 
postgres_1  | 
postgres_1  | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
postgres_1  | 
postgres_1  | 2022-11-07 23:27:34.130 UTC [48] LOG:  received fast shutdown request
postgres_1  | waiting for server to shut down....2022-11-07 23:27:34.133 UTC [48] LOG:  aborting any active transactions
postgres_1  | 2022-11-07 23:27:34.135 UTC [48] LOG:  worker process: logical replication launcher (PID 55) exited with exit code 1
postgres_1  | 2022-11-07 23:27:34.135 UTC [50] LOG:  shutting down
postgres_1  | 2022-11-07 23:27:34.157 UTC [48] LOG:  database system is shut down
postgres_1  |  done
postgres_1  | server stopped
postgres_1  | 
postgres_1  | PostgreSQL init process complete; ready for start up.
postgres_1  | 
postgres_1  | 2022-11-07 23:27:34.254 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres_1  | 2022-11-07 23:27:34.254 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres_1  | 2022-11-07 23:27:34.259 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres_1  | 2022-11-07 23:27:34.283 UTC [76] LOG:  database system was shut down at 2022-11-07 23:27:34 UTC
postgres_1  | 2022-11-07 23:27:34.294 UTC [1] LOG:  database system is ready to accept connections

CodePudding user response:

The issue could be in how you're exposing your database container in the docker-compose.yaml file. "connection refused" is a typical error in this scenario. Usually, I export the ports in a different way (in this code I reported only the relevant parts):

docker-compose.yaml

version: "3"
services:
  db:
    image: postgres
    environment:
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_USER=postgres
    ports:
      - "5432:5432"

main.go

package main

import (
    "database/sql"
    "log"

    _ "github.com/lib/pq"
)

func main() {
    // Connecting to database
    db, err := sql.Open("postgres", "host=127.0.0.1 user=postgres password=postgres dbname=postgres port=5432 sslmode=disable")
    if err != nil {
        log.Fatalf("Can't connect to postgresql: %v", err)
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        log.Fatalf("Can't ping database: %v", err)
    }
}

With this solution, I was able to successfully ping the Postgres database directly from the code. Let me know if that helps.

Edit

There is a little difference in the way you interact with db instance:

  1. If you're trying to contact the db directly from your host machine (like in the main.go file), you've to refer to it with the IP address of your machine (e.g., 127.0.0.1).
  2. If you're trying to contact the db from your web container, you've to use something like postgres://db:5432 with db as the hostname.

Let me know if this clarifies a little bit.

  • Related