I'm running Postgres DB with pg-admin and GO on the docker-compose.
Problem: I can connect from pg-admin to Postgres. But cannot establish a connection from Go.
I tried different combinations of authentication string but it does not work. String format same as here https://github.com/karlkeefer/pngr - but different container name - database
(ERROR) Connection URl:
backend_1 | 2021/08/08 14:24:40 DB connection: database://main:fugZwypczB94m0LP7CcH#postgres:5432/temp_db?sslmode=disable
backend_1 | 2021/08/08 14:24:40 Unalble to open DB connection: dial tcp 127.0.0.1:5432: connect: connection refused
(URI generation same as here https://github.com/karlkeefer/pngr)
Docker:
version: '3.8'
services:
backend:
restart: always
build:
context: backend
target: dev
volumes:
- ./backend:/root
ports:
- "5000:5000"
env_file: .env
depends_on:
- database
database:
build: database
restart: always
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
PGDATA: /var/lib/postgresql/data
volumes:
- ./database/data:/var/lib/postgresql/data
- ./logs/databse:/var/log/postgresql
- ./database/migrations:/docker-entrypoint-initdb.d/migrations
ports:
- "5432:5432"
database-admin:
image: dpage/pgadmin4:5.5
restart: always
environment:
PGADMIN_DEFAULT_EMAIL: ${PG_ADMIN_EMAIL}
PGADMIN_DEFAULT_PASSWORD: ${PG_ADMIN_PASSWORD}
PGADMIN_LISTEN_PORT: 80
ports:
- "8080:80"
volumes:
- ./database/admin:/var/lib/pgadmin
links:
- "database:pgsql-server"
depends_on:
- database
volumes:
database:
database-admin:
Environment:
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=temp_db
POSTGRES_USER=main
POSTGRES_PASSWORD=fugZwypczB94m0LP7CcH
PG_ADMIN_EMAIL=admin#temp.com
PG_ADMIN_PASSWORD=ayzi2ta8f1TnX3vKQSN1
PG_ADMIN_PORT=80
GO Code:
db, err = sqlx.Open("postgres", str)
str
func buildConnectionString() string {
user := os.Getenv("POSTGRES_USER")
pass := os.Getenv("POSTGRES_PASSWORD")
if user == "" || pass == "" {
log.Fatalln("You must include POSTGRES_USER and POSTGRES_PASSWORD environment variables")
}
host := os.Getenv("POSTGRES_HOST")
port := os.Getenv("POSTGRES_PORT")
dbname := os.Getenv("POSTGRES_DB")
if host == "" || port == "" || dbname == "" {
log.Fatalln("You must include POSTGRES_HOST, POSTGRES_PORT, and POSTGRES_DB environment variables")
}
str := fmt.Sprintf("database://%s:%s#%s:%s/%s?sslmode=disable", user, pass, host, port, dbname)
log.Println("DB connection: " + str)
return str
}
Thanks in advance!
You reference the database hostname as postgres (POSTGRES_HOST=postgres) which is fine, but the container/service name is database.
Either change the name in your compose.yaml from database to postgres or add an explicit hostname field:
database:
build: database
restart: always
hostname: postgres # <- add this
You may also want to add a dedicated network for multiple container services to talk to one another (or prevent others from). To do this, add this to each service your want to use a specific network e.g.
database:
# ...
networks:
- mynet
backend:
# ...
networks:
- mynet
and define the network at the end of your compose.yaml
networks:
mynet:
name: my-shared-db-network
Related
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/gorm#v1.24.1/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.
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
package main
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(1 * time.Second) // change back to 10s
}
if err != nil {
log.Println("Producer: Error Connecting to Database")
} else {
log.Println("Producer: Connection Opened to Database")
}
}
func main() {
ConnectDB()
}
No relevant changes here.
.env
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=postgres
DATABASE_HOST=imgress-db
DATABASE_PORT=5432
Also here nothing to mention.
Dockerfile
FROM golang:1.19.3-alpine3.17 AS build
WORKDIR /go/src/app
COPY ./main.go ./main.go
RUN go mod init pgdockercompose
RUN go mod tidy
RUN go build -o ./bin/webserver ./main.go
FROM alpine:3.17
COPY --from=build /go/src/app/bin /go/bin
EXPOSE 8080
ENTRYPOINT go/bin/webserver
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
version: "3.9"
services:
imgress-producer:
build: "."
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
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}
ports:
- 5432:5432
restart: always
networks:
- imgress-network
networks:
imgress-network:
driver: bridge
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
app:
// other stuff
- network_mode: "host"
db:
- expose:
- "5432" // or the port you want
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.
Here is my docker compose:
version: "3.9"
services:
app:
container_name: app
build:
context: ./..
dockerfile: deployments/Dockerfile
env_file:
- ../configs/config.env
ports:
- ${APP_PORT:-8080}:8080
networks:
- network
restart: always
db:
image: mongo:latest
container_name: mongodb
restart: always
env_file:
- ../configs/config.env
ports:
- ${MONGODB_PORT:-27017}:27017
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGODB_ROOT_USER:-admin}
MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_ROOT_PASSWORD:-admin}
volumes:
- ../assets/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh
adminer:
image: adminer
container_name: db-adminer
restart: always
ports:
- ${ADMINER_PORT:-17860}:8080
networks:
- network
depends_on:
- db
networks:
network:
driver: bridge
Here is my mongo-init.sh file:
use newdb
db.createUser(
{
user: admin,
pwd: admin,
roles: [
{
role: "readWrite",
db: "newdb"
}
]
}
);
Here I am trying to connect to the database, but I get the following error: topology is connected or connecting
client, err := mongo.Connect(ctx, options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%s#%s:%s",
cfg.DbUsername, cfg.DbPassword, cfg.DbHost, cfg.DbPort)))
I don't understand what the error might be, since everything is fine in the env file and all the variables match the authentication parameters in mongo
check this out:
services:
productinfo:
container_name: product_cntnr
build: ./api-productinfo-service
image: arc1999/api-productinfo-service
ports:
- '8090:8090'
depends_on:
db:
condition: service_healthy
links:
- db
scraping:
build: ./api-scraping-service
image: arc1999/api-scraping-service
ports:
- '8080:8080'
depends_on:
db:
condition: service_healthy
links:
- db
db:
image: mongo:latest
container_name: mongo_db
# environment:
# MONGO_INITDB_ROOT_USERNAME: root
# MONGO_INITDB_ROOT_PASSWORD: rootpassword
ports:
- 27017:27017
volumes:
- mongodb_data_container:/data/db
healthcheck:
test: echo 'db.runCommand("ping").ok'
interval: 10s
timeout: 10s
retries: 5
volumes:
mongodb_data_container:
func InitDb() {
host := "mongodb://mongo_db:27017"
rb := bson.NewRegistryBuilder()
rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.M{}))
clientOptions := options.Client().ApplyURI(host).SetRegistry(rb.Build())
// Connect to MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Panicln(err)
}
err = client.Ping(context.TODO(), nil)
if err != nil {
log.Panicln(err)
}
db = client.Database(os.Getenv("MONGO_DB_NAME"))
fmt.Println("Connected to MongoDB!")
}
I'm getting the following error when dockerizing a node postgres database using sequelize as an orm backend
Unhandled rejection SequelizeConnectionRefusedError: connect
ECONNREFUSED 127.0.0.1:5432 app_1 | at
connection.connect.err
(/home/app/node_modules/sequelize/lib/dialects/postgres/connection-manager.js:170:24)
These lines of code seems to be the culprit, docker should not be connecting these credentials as this is for my local.
if (process.env.NODE_ENV === "production") {
var sequelize = new Sequelize(process.env.DATABASE_URL);
} else {
// docker is looking at these credentials..... when it should not
var sequelize = new Sequelize("elifullstack", "eli", "", {
host: "127.0.0.1",
dialect: "postgres",
pool: {
max: 100,
min: 0,
idle: 200000,
// #note https://github.com/sequelize/sequelize/issues/8133#issuecomment-359993057
acquire: 1000000,
},
});
}
docker-compose.yml
# docker-compose.yml
version: "3"
services:
app:
build: ./server
depends_on:
- database
ports:
- 5000:5000
environment:
# database refers to the database server at the bottom called "database"
- PSQL_HOST=database
- PSQL_USER=postgres
- PORT=5000
- PSQL_NAME=elitypescript
command: npm run server
client:
build: ./client
image: react_client
links:
- app
working_dir: /home/node/app/client
volumes:
- ./:/home/node/app
ports:
- 3001:3001
command: npm run start
env_file:
- ./client/.env
database:
image: postgres:9.6.8-alpine
volumes:
- database:/var/lib/postgresql/data
ports:
- 3030:5432
volumes:
database:
./server/dockerFile
FROM node:10.6.0
COPY . /home/app
WORKDIR /home/app
COPY package.json ./
RUN npm install
EXPOSE 5000
I looked at other similar questions like the following, but it ultimately did not help solve the issue.
Docker - SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306
SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306
I solved it...
What i did was change this
host: "127.0.0.1",
to this
let sequelize;
if (process.env.NODE_ENV === "production") {
sequelize = new Sequelize(process.env.DATABASE_URL);
} else {
sequelize = new Sequelize(
process.env.POSTGRES_DB || "elitypescript",
process.env.POSTGRES_USER || "eli",
"",
{
host: process.env.PSQL_HOST || "localhost",
dialect: "postgres",
pool: {
max: 100,
min: 0,
idle: 200000,
// #note https://github.com/sequelize/sequelize/issues/8133#issuecomment-359993057
acquire: 1000000,
},
}
);
}
that way the host would be set to docker environment variable like this
PSQL_HOST: database
and that connects to
database:
image: postgres:9.6.8-alpine
volumes:
- database:/var/lib/postgresql/data
ports:
- 3030:5432
Edit
# docker-compose.yml
version: "3"
services:
app:
build: ./server
depends_on:
- database
ports:
- 5000:5000
environment:
PSQL_HOST: database
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_DB: ${POSTGRES_DB:-elitypescript}
command: npm run server
client:
build: ./client
image: react_client
links:
- app
working_dir: /home/node/app/client
volumes:
- ./:/home/node/app
ports:
- 3001:3001
command: npm run start
env_file:
- ./client/.env
database:
image: postgres:9.6.8-alpine
volumes:
- database:/var/lib/postgresql/data
ports:
- 3030:5432
volumes:
database:
Trying to open Database but it is saying password authentication failed for user "postgres"
I am not able to find the root cause of this problem.First time,i am using Docker. Pleas help
func openDB() (*sqlx.DB, error) {
q := url.Values{}
q.Set("sslmode", "disable")
q.Set("timezone", "utc")
u := url.URL{
Scheme: "postgres",
User: url.UserPassword("postgres", "postgres"),
Host: "localhost",
Path: "postgres",
RawQuery: q.Encode(),
}
fmt.Println(u.String())
// fmt.Println(u.String()) is
// postgre://postgres:postgres#localhost/postgres?sslmode=disable&timezone=utc
return sqlx.Open("postgres", u.String())
}
docker-compose.yaml looks like this.
version: '3'
networks:
shared-network:
driver: bridge
services:
db:
container_name: sales_db
networks:
- shared-network
image: postgres:11.1-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
There was no problem in code. I changed the port eveything is working now.
func openDB() (*sqlx.DB, error) {
q := url.Values{}
q.Set("sslmode", "disable")
q.Set("timezone", "utc")
u := url.URL{
Scheme: "postgres",
User: url.UserPassword("postgres", "postgres"),
Host: "localhost:5433", // change here
Path: "postgres",
RawQuery: q.Encode(),
}
fmt.Println(u.String())
// fmt.Println(u.String()) is
// postgre://postgres:postgres#localhost/postgres?sslmode=disable&timezone=utc
return sqlx.Open("postgres", u.String())
}
and
version: '3'
networks:
shared-network:
driver: bridge
services:
db:
container_name: sales_db
networks:
- shared-network
image: postgres:11.1-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5433:5432 //change here
Getting this error when conneccting golang container to postgres.
pq: Could not detect default username. Please provide one explicitly
I have tried many usernames and password combinations with no luck. What username combination should I be using?
docker-compose code is:
version: '3.6'
services:
postgres:
image: postgres:11.1-alpine
ports:
- '5432:5432'
#network_mode: bridge
container_name: postgres
environment:
POSTGRES_USER: 'user'
POSTGRES_PASSWORD: 'password'
POSTGRESS_DB: 'db_amex01'
volumes:
- ./init:/docker-entrypoint-initdb.d/
todo:
build: ./go_amex/
depends_on:
- "postgres"
restart: always
# ports:
# - "8000:8080"
./go_amex/main.go
db, err := gorm.Open("postgres", "host='postgres'&user=user#localhost&port=5432&dbname='todo'&password='password'&sslmode=disable")
if err != nil {
fmt.Println("============ exiting ==========")
fmt.Println(err)
panic("failed to connect database cc")
}
defer db.Close()
Github code for the challenge
Try this:
version: '3'
services:
postgres:
image: kartoza/postgis:9.6-2.4
ports:
- "5432:5432"
environment:
POSTGRES_USER: developer
POSTGRES_DBNAME: somedb
POSTGRES_PASS: somepass
volumes:
- $HOME/data/postgres:/var/lib/postgresql/data
config for database in yaml
sqlBind := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable",
"developer",
"somepass",
"somedb",
)