Golang not connecting to Postgres thought gorm and hosted by Docker

Hi everyone!

Golang container isn’t finding Postgres db’s. I have one idea but can’t implement this logic. Is it possible to retry to connect to database, if connection is refused?
for example…

func Init() {
	authConnect := fmt.Sprintf( "host=%s port=%s user=%s dbname=%s sslmode=disable password=%s",
		os.Getenv( "AUTH_DB_HOST" ),
		os.Getenv( "AUTH_DB_PORT" ),
		os.Getenv( "AUTH_DB_USER" ),
		os.Getenv( "AUTH_DB_NAME" ),
		os.Getenv( "AUTH_DB_PASSWORD" ) )
	
	AuthConnect:
	AuthDB, err = gorm.Open( "postgres", authConnect )

	if err != nil {
		log.Printf("Got error when connect database `auth`, the error is '%v'", err)
		goto AuthConnect
	}

	userConnect := fmt.Sprintf( "host=%s port=%s user=%s dbname=%s sslmode=disable password=%s",
		os.Getenv( "USER_DB_HOST" ),
		os.Getenv( "USER_DB_PORT" ),
		os.Getenv( "USER_DB_USER" ),
		os.Getenv( "USER_DB_NAME" ),
		os.Getenv( "USER_DB_PASSWORD" ) )

	UserConnect:
	UserDB, err = gorm.Open("postgres", userConnect )

	if err != nil {
		log.Fatalf("Got error when connect database `user`, the error is '%v'", err)
		goto UserConnect
	}
}

If you have any suggestions please help me.

Here are my code, logs and other details.

func Init() {
	authConnect := fmt.Sprintf( "host=%s port=%s user=%s dbname=%s sslmode=disable password=%s",
		os.Getenv( "AUTH_DB_HOST" ),
		os.Getenv( "AUTH_DB_PORT" ),
		os.Getenv( "AUTH_DB_USER" ),
		os.Getenv( "AUTH_DB_NAME" ),
		os.Getenv( "AUTH_DB_PASSWORD" ) )

	AuthDB, err = gorm.Open( "postgres", authConnect )

	if err != nil {
		log.Fatalf("Got error when connect database `auth`, the error is '%v'", err)
	}

	userConnect := fmt.Sprintf( "host=%s port=%s user=%s dbname=%s sslmode=disable password=%s",
		os.Getenv( "USER_DB_HOST" ),
		os.Getenv( "USER_DB_PORT" ),
		os.Getenv( "USER_DB_USER" ),
		os.Getenv( "USER_DB_NAME" ),
		os.Getenv( "USER_DB_PASSWORD" ) )

	UserDB, err = gorm.Open("postgres", userConnect )

	if err != nil {
		log.Fatalf("Got error when connect database `user`, the error is '%v'", err)
	}
}

After starting the container I get this message.

auth_1     | 2017/09/07 12:04:32 Got error when connect database `auth`, the error is 'dial tcp 127.0.0.1:5437: getsockopt: connection refused'

My docker-compose.yml

version: '3'
services:
  user_db:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRESS_PASSWORD=postgres
      - POSTGRES_DB=user
    ports:
      - "5432:5432"
  auth_db:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRESS_PASSWORD=postgres
      - POSTGRES_DB=auth
    ports:
      - "5437:5432"
  auth:
    build:
      context: .
      dockerfile: ./auth/Dockerfile
    environment:
      - AUTOMIGRATE=true
      - AUTH_DB_HOST=localhost
      - USER_DB_HOST=localhost
      - AUTH_DB_PORT=5437
      - USER_DB_PORT=5432
      - AUTH_DB_USER=postgres
      - USER_DB_USER=postgres
      - AUTH_DB_NAME=auth
      - USER_DB_NAME=user
      - AUTH_DB_PASSWORD=postgres
      - USER_DB_PASSWORD=postgres
    ports:
      - "8070:8070"
    depends_on:
      - user_db
      - auth_db
  user:
    build:
      context: .
      dockerfile: ./user/Dockerfile
    environment:
      - AUTOMIGRATE=true
    ports:
      - "8090:8090"
    depends_on:
      - user_db

My docker-compose logs

Attaching to grsuser_auth_db_1, grsuser_user_db_1, grsuser_user_1, grsuser_auth_1
auth_db_1  | The files belonging to this database system will be owned by user "postgres".
auth_db_1  | This user must also own the server process.
auth_db_1  | 
auth_db_1  | The database cluster will be initialized with locale "en_US.utf8".
auth_db_1  | The default database encoding has accordingly been set to "UTF8".
auth_db_1  | The default text search configuration will be set to "english".
auth_1     | 2017/09/07 12:04:32 Got error when connect database `auth`, the error is 'dial tcp 127.0.0.1:5437: getsockopt: connection refused'
auth_db_1  | 
auth_db_1  | Data page checksums are disabled.
user_db_1  | The files belonging to this database system will be owned by user "postgres".
auth_db_1  | 
user_db_1  | This user must also own the server process.
user_db_1  | 
user_db_1  | The database cluster will be initialized with locale "en_US.utf8".
auth_db_1  | fixing permissions on existing directory /var/lib/postgresql/data ... ok
auth_db_1  | creating subdirectories ... ok
user_db_1  | The default database encoding has accordingly been set to "UTF8".
auth_db_1  | selecting default max_connections ... 100
user_db_1  | The default text search configuration will be set to "english".
auth_db_1  | selecting default shared_buffers ... 128MB
user_db_1  | 
user_db_1  | Data page checksums are disabled.
auth_db_1  | selecting dynamic shared memory implementation ... posix
auth_db_1  | creating configuration files ... ok
user_db_1  | 
auth_db_1  | running bootstrap script ... ok
user_db_1  | fixing permissions on existing directory /var/lib/postgresql/data ... ok
user_1     | Now listening on: http://localhost:8090
auth_db_1  | performing post-bootstrap initialization ... ok
user_db_1  | creating subdirectories ... ok
user_db_1  | selecting default max_connections ... 100
auth_db_1  | 
user_1     | Application started. Press CTRL+C to shut down.
auth_db_1  | WARNING: enabling "trust" authentication for local connections
user_db_1  | selecting default shared_buffers ... 128MB
auth_db_1  | You can change this by editing pg_hba.conf or using the option -A, or
user_1     | Now listening on: http://localhost:8090
user_db_1  | selecting dynamic shared memory implementation ... posix
auth_db_1  | --auth-local and --auth-host, the next time you run initdb.
user_1     | Application started. Press CTRL+C to shut down.
user_db_1  | creating configuration files ... ok
auth_db_1  | syncing data to disk ... ok
user_db_1  | running bootstrap script ... ok
auth_db_1  | 
auth_db_1  | Success. You can now start the database server using:
user_db_1  | performing post-bootstrap initialization ... ok
user_db_1  | syncing data to disk ... ok
user_db_1  | 
user_db_1  | Success. You can now start the database server using:
user_db_1  | 
user_db_1  |     pg_ctl -D /var/lib/postgresql/data -l logfile start
auth_db_1  | 
user_db_1  | 
auth_db_1  |     pg_ctl -D /var/lib/postgresql/data -l logfile start
user_db_1  | 
user_db_1  | WARNING: enabling "trust" authentication for local connections
auth_db_1  | 
user_db_1  | You can change this by editing pg_hba.conf or using the option -A, or
auth_db_1  | ****************************************************
user_db_1  | --auth-local and --auth-host, the next time you run initdb.
auth_db_1  | WARNING: No password has been set for the database.
auth_db_1  |          This will allow anyone with access to the
user_db_1  | ****************************************************
auth_db_1  |          Postgres port to access your database. In
user_db_1  | WARNING: No password has been set for the database.
auth_db_1  |          Docker's default configuration, this is
user_db_1  |          This will allow anyone with access to the
auth_db_1  |          effectively any other container on the same
user_db_1  |          Postgres port to access your database. In
auth_db_1  |          system.
auth_db_1  | 
auth_db_1  |          Use "-e POSTGRES_PASSWORD=password" to set
user_db_1  |          Docker's default configuration, this is
auth_db_1  |          it in "docker run".
user_db_1  |          effectively any other container on the same
auth_db_1  | ****************************************************
user_db_1  |          system.
auth_db_1  | waiting for server to start....LOG:  could not bind IPv6 socket: Cannot assign requested address
auth_db_1  | HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
auth_db_1  | LOG:  database system was shut down at 2017-09-07 11:55:29 UTC
auth_db_1  | LOG:  MultiXact member wraparound protections are now enabled
auth_db_1  | LOG:  database system is ready to accept connections
auth_db_1  | LOG:  autovacuum launcher started
auth_db_1  |  done
auth_db_1  | server started
auth_db_1  | CREATE DATABASE
auth_db_1  | 
auth_db_1  | ALTER ROLE
auth_db_1  | 
auth_db_1  | 
user_db_1  | 
user_db_1  |          Use "-e POSTGRES_PASSWORD=password" to set
user_db_1  |          it in "docker run".
user_db_1  | ****************************************************
user_db_1  | waiting for server to start....LOG:  could not bind IPv6 socket: Cannot assign requested address
user_db_1  | HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
user_db_1  | LOG:  database system was shut down at 2017-09-07 11:55:29 UTC
user_db_1  | LOG:  MultiXact member wraparound protections are now enabled
user_db_1  | LOG:  database system is ready to accept connections
user_db_1  | LOG:  autovacuum launcher started
user_db_1  |  done
auth_db_1  | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
auth_db_1  | 
auth_db_1  | LOG:  received fast shutdown request
user_db_1  | server started
user_db_1  | CREATE DATABASE
user_db_1  | 
user_db_1  | ALTER ROLE
user_db_1  | 
user_db_1  | 
user_db_1  | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
user_db_1  | 
user_db_1  | LOG:  received fast shutdown request
auth_db_1  | waiting for server to shut down....LOG:  aborting any active transactions
auth_db_1  | LOG:  autovacuum launcher shutting down
auth_db_1  | LOG:  shutting down
auth_db_1  | LOG:  database system is shut down
auth_db_1  |  done
auth_db_1  | server stopped
auth_db_1  | 
auth_db_1  | PostgreSQL init process complete; ready for start up.
auth_db_1  | 
auth_db_1  | LOG:  database system was shut down at 2017-09-07 11:55:34 UTC
auth_db_1  | LOG:  MultiXact member wraparound protections are now enabled
auth_db_1  | LOG:  database system is ready to accept connections
auth_db_1  | LOG:  autovacuum launcher started
auth_db_1  | LOG:  received smart shutdown request
auth_db_1  | LOG:  autovacuum launcher shutting down
user_db_1  | waiting for server to shut down....LOG:  aborting any active transactions
user_db_1  | LOG:  autovacuum launcher shutting down
user_db_1  | LOG:  shutting down
user_db_1  | LOG:  database system is shut down
user_db_1  |  done
user_db_1  | server stopped
user_db_1  | 
user_db_1  | PostgreSQL init process complete; ready for start up.
user_db_1  | 
user_db_1  | LOG:  database system was shut down at 2017-09-07 11:55:34 UTC
user_db_1  | LOG:  MultiXact member wraparound protections are now enabled
user_db_1  | LOG:  autovacuum launcher started
user_db_1  | LOG:  database system is ready to accept connections
auth_db_1  | LOG:  shutting down
auth_db_1  | LOG:  database system is shut down
auth_db_1  | LOG:  database system was shut down at 2017-09-07 12:00:31 UTC
auth_db_1  | LOG:  MultiXact member wraparound protections are now enabled
auth_db_1  | LOG:  database system is ready to accept connections
auth_db_1  | LOG:  autovacuum launcher started
grsuser_auth_1 exited with code 1

Regards, Khachatur!

The hosts of your databases inside the composed docker environment should be user_db and auth_db. Docker uses the names of the services as a DNS-ready name.

Since all of those services are running inside different containers, none of them can be localhost for any other container.

NB: This problem is related to docker, not go, you’d have had it in ruby, python, c, or whatever as well.

2 Likes

You are saying that:

auth:
    build:
      context: .
      dockerfile: ./auth/Dockerfile
    environment:
      - AUTOMIGRATE=true
      - AUTH_DB_HOST=auth_db
      - USER_DB_HOST=user_db
      - AUTH_DB_PORT=5437
      - USER_DB_PORT=5432
      - AUTH_DB_USER=postgres
      - USER_DB_USER=postgres
      - AUTH_DB_NAME=auth
      - USER_DB_NAME=user
      - AUTH_DB_PASSWORD=postgres
      - USER_DB_PASSWORD=postgres
    ports:
      - "8070:8070"
    depends_on:
      - user_db
      - auth_db

or

AuthDB, err = gorm.Open( "postgres", "host=auth_db user=postgres dbname=auth sslmode=disable password=postgres" )

if err != nil {
	log.Fatalf("Got error when connect database `auth`, the error is '%v'", err)
}

UserDB, err = gorm.Open("postgres", "host=user_db user=postgres dbname=user sslmode=disable password=postgres" )

if err != nil {
	log.Fatalf("Got error when connect database `user`, the error is '%v'", err)
}

I’m saying that instead of configuring neighbouring hosts from the docker compose environment as localhost with their corresponding “local” docker-compose names.

I’m not really sure what you are asking by copying snippets from above.