One of the biggest benefits of using docker for me has been the fact that it makes developing code with databases much simpler.
Whenever I’m building an app, I tend to use postgres as the database. Pre-docker, this meant installing postgres locally on my machine, running the server, creating the database, adding the required users and persmissions and finally running the app locally to test and develop. I’ve spent hours going through this.
Post-docker, things became much much simpler, especially with docker-compose. With docker-compose now I can have a postgres server up and running and configured as I want within 5-10min and I don’t have to worry about installing it and running it on my machine anymore. This is was magical. I could now focus spending my time on more important things. Like looking at cat gifs.
Today however, wasn’t one of those days :(
Scouring the internet for the initial config to go on, I wrote my docker-compose.yml as shown.
|
|
And used the following string for the postgres connection in the app
postgres://user:[email protected]:5432/db?sslmode=disable
Only to be met with the unexpected error, when running both the containers
server_1 | 2020/12/13 19:42:16 couldn't get driver: failed to connect to `host=127.0.0.1 user=postgres database=postgres`: dial error (dial tcp 127.0.0.1:5432: connect: connection refused)
server_1 | exit status 1
And while I’ve done this a couple of times before I couldn’t wrap my head around why this error was popping up.
Debug time Link to heading
Step 1: Typo Link to heading
Without much resolute my first instinct was to check for typos, after cross-verifying, I found everything to be ok.
Step 2: Brute force Link to heading
Not particularly proud of this, but I did try swapping 127.0.0.1 with localhost to get the same error. Hint: I was spot on as to where the error was, but just totally wrong about how to go about it.
Step 3: Bash Link to heading
This I like. To diagnose the problem, I ran ❯ docker-compose exec server bash
. This dropped me right into the shell of the server app. From here these are the following debugging steps I followed
- Install psql client
- Try to manually connect using the psql client. This failed.
- Check if the port is being used using netstat. No, it wasn’t.
- Realize that this is a network issue. Ahaa!
Docker Compose Network Link to heading
Putting it shortly, docker compose isolates each of the containers network. This is done by adding them to the <myapp>_default
which is a newly created network, where <myapp>
is the name of the directory. Under this each of the containers is added via it’s name. In our case that would be postgres
and server
. These are like DNS A-records, which means using postgres
would resolve to the IP of the postgres container and so on. Each of the container can use these names to connect to the other containers.
Solution Link to heading
Now that we know the exact problem, all we need to do is change our host in the postgres connection string to postgres
from 127.0.0.1
.
postgres://user:pass@postgres:5432/db?sslmode=disable
Alternate Solution Link to heading
Another way is to add network_mode: bridge
to each container to put them all under the same network. While this is a topic in itself, this bridges the network between the two containers so that they co-exist on the same network.