I have a web server built using golang. It works successfully when I test it locally.
However, when I build a docker image for my web server, it can't connect to a running Postgres container.
Here is my docker-compose.yml
:
version: '2'
services:
go:
image: golang:1.7
volumes:
- ./:/server/http
ports:
- "80:8080"
links:
- postgres
- mongodb
- redis
environment:
DEBUG: 'true'
PORT: '8080'
postgres:
image: onjin/alpine-postgres:9.5
restart: unless-stopped
ports:
- "5432:5432"
environment:
LC_ALL: C.UTF-8
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
mongodb:
image: mvertes/alpine-mongo:3.2.3
restart: unless-stopped
ports:
- "27017:27017"
redis:
image: sickp/alpine-redis:3.2.2
restart: unless-stopped
ports:
- "6379:6379"
My Dockerfile
:
FROM golang:1.7
RUN mkdir -p /home/app
WORKDIR /home/app
COPY . /home/app
RUN make deps && make
ENTRYPOINT ["./bin/api-test"]
EXPOSE 8080
The Postgres connection string I am using:
postgresql://user:pass@host/mydb?sslmode=disable
For host, I tried localhost
and it returns the following error:
dial tcp [::1]:5432: getsockopt: connection refused
Tried postgres
and it returns the following:
dial tcp 202.71.99.194:5432: getsockopt: connection refused
Tried the IP address I get running this command which returns 172.19.0.3
:
docker inspect apitest_postgres_1 | grep IPAddress
where apitest_postgres_1
is Postgres container name. It also returned this error:
dial tcp 172.19.0.3:5432: getsockopt: connection timed out
Can you please tell me what I am missing here? I am inexperienced with docker and this took a long time investigating for a solution.
Edit: I run my golang docker using this command:
docker run --env-file ./example.env --rm -it -p 8080:8080 api-test
example.env
is the file contains my environment vars.
Edit 2: I changed the connection string to the following:
postgresql://user:pass@postgres:5432?sslmode=disable
It returns the following error:
dial tcp: lookup postgres on 192.168.65.1:53: no such host
I'm getting the idea that my mac is the issue here. My default DNS is 8.8.8.8
which should not be a problem.
Looks like you're pulling go image instead of building you're own image.
Instead of image: golang:1.7
replace it with build: .
to build and use your Dockerfile
.
Also you might need to pass postgres environment variables DB_HOST
, DB_USER
, DB_PASS
etc. you can achieve that but creating for example docker.env
file and then add env_file
under your go app docker-compose.yml
file:
Example docker.env :
DB_HOST=postgres
DB_USER=user
DB_PASS=pass
DB_NAME=mydb
Corrected docker-compose.yml :
version: '2'
services:
app:
build: .
volumes:
- ./:/server/http
ports:
- "80:8080"
links:
- postgres
- mongodb
- redis
environment:
DEBUG: 'true'
PORT: '8080'
env_file:
- docker.env
postgres:
image: onjin/alpine-postgres:9.5
restart: unless-stopped
ports:
- "5432:5432"
environment:
LC_ALL: C.UTF-8
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
mongodb:
image: mvertes/alpine-mongo:3.2.3
restart: unless-stopped
ports:
- "27017:27017"
redis:
image: sickp/alpine-redis:3.2.2
restart: unless-stopped
ports:
- "6379:6379"
In order to make a connection to postgres in docker compose becomes established, you need to replace localhost or 127.0.0.1 or postgres in your connection string with the name of the container being mentioned in your docker compose file.
For example, in your docker-compose.yaml file create database like this:
db:
container_name: composepostgres
image: postgres
environment:
and then, in your code when creating your connection string, avoid using 127.0.0.1
or localhost
or postgres
, and instead use composepostgres
in the place of them.
If not doing so, you will face with dial tcp 127.0.0.1:5432: connect: connection refused
error.
Take a look a this documentation : https://docs.docker.com/engine/userguide/networking/default_network/configure-dns/
Then, regarding the links in you docker-compose file, replace "host" by "postgres" in you connection string :
postgresql://user:pass@postgres/mydb?sslmode=disable
Let the embedded DNS server do the mapping work because the ip address may change every time you recreate the container.
Also, ensure postgres allows connection (maybe limited to localhost)