How to connect a Docker application to a Postgres database on the host machine

Connecting a Docker application to non-Dockerized Postgres database from is a more complicated task than you would think. While a Docker container can easily communicate with other containers running on the same machine, it can't easily find how to connect to the host machine running it. This is because of the way Docker handles networking, by isolating the containers on its own virtual network which doesn't include the computer hosting Docker.

A while back I published How to connect to an external Postgres database from a Docker container, which showed you how to tinker with the settings on your local machine or any other computer in your local network so that your Dockerized app can connect to Postgres. I've recently discovered an alternative method which is even faster. Here's how I do it now:

version: '3'

services:
  myapp:
    build: .
    command: "bundle exec rails s"
    environment:
      - DATABASE_URL=${DATABASE_URL} # Connection string to the database goes here
      - PGPASSWORD=${PGPASSWORD}
      - RAILS_ENV=${RAILS_ENV:-development}
      - RAILS_LOG_TO_STDOUT=true
    network_mode: host
    tty: true

Notice how in my docker-compose the network_mode is "host". This value will cause the container to run from the host's network directly - no isolation of the container onto its own network. That means localhost in the container will point to the localhost of your machine. You can then connect to Postgres in the command line from within the container like this:

$ docker-compose run myapp /bin/sh

/app # psql -U postgres -h localhost
psql (10.5, server 9.6.11)
Type "help" for help.

postgres=# 

Note that it's necessary to specify the -h localhost parameter. Also, if you make use of the PGPASSWORD environment variable you can have that set to the database password so that it won't prompt you to type it in.