66

I'm trying to use a Docker container to run a PostgreSQL server, and connect with it from my host machine.

My configuration is:

  • Host machine: Mac OS X 10.10.5
  • Docker 1.10.1

I've done this:

Step 1: create a volume for permanent postgres data

docker volume create --name postgres_data

Step 2: Start the postgres instance

UPDATE: As suggested in comments, I specified port mapping when running the container

docker run --name my_postgres_container -e POSTGRES_PASSWORD=my_password -v postgres_data:/var/lib/postgresql/data -p 5432:5432 -d postgres:9.1

Step 3: connect to Docker instance by doing this:

docker run -it --link my_postgres_container:postgres --rm postgres:9.1 sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

But I want to connect to that instance just by:

psql -h localhost -p 5432 -U postgres

Like if I had installed Postgres locally in my host machine.

The problem is port 5432 is not exposed. So, I can't connect with it:

sudo lsof -i -P | grep -i "listen" --> no port 5432 open

UPDATE 2: Even stranger. I've also done this:

Stop Docker. Then, run a normal PostgreSQL 9.4.4 instance in my host machine (no docker involved here, just postgres running in my Mac OS X host, listening on port 5432). Everything is normal:

sudo lsof -i -P | grep -i "postgres"

postgres  14100          jorge    6u  IPv4 0x780274158cebef01      0t0  TCP localhost:5432 (LISTEN)

I can connect with my local postgres instance without any problem (look the output of the command: is the postgres compiled for Mac OS X, my host):

psql -h localhost -U postgres -c "select version()"
                                                                version
---------------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 9.4.4 on x86_64-apple-darwin14.3.0, compiled by Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn), 64-bit
(1 row)

Now the fun part. I start my Docker instance again, while the host PostgreSQL instance is running.

It starts! (and it shouldn't). I can even connect using docker run...

docker run -it --link my_postgres_instance:postgres --rm postgres:9.1 sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

If I run select version() now, it shows postgres running inside my docker instance at the same time postgres is running in my host, out of docker, using the same 5432 port. (Look at the ouput, is postgres compiled for Debian, the OS inside the postgres:9.1 container)

postgres=# select version();
                                            version
------------------------------------------------------------------------------------------------
 PostgreSQL 9.1.20 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
(1 row)

Why?

Does it make sense? My final goal is to run a Django app in another Docker container and connect with my Postgres instance. How could I do that?

Jorge Arévalo
  • 2,858
  • 5
  • 36
  • 44

10 Answers10

134

It's 2018 and I just had a similar problem. The solution for me seemed to be with the order of props to docker. e.g. this resulted in no port being exposed;

docker run -d --name posttest postgres:alpine -e POSTGRES_PASSWORD=fred -p 5432:5432

while this worked fine (image exposed port 5432 as expected);

docker run --name posttest -d -p 5432:5432 -e POSTGRES_PASSWORD=fred postgres:alpine

MrGreg
  • 1,498
  • 1
  • 10
  • 7
  • 1
    Could someone please explain why this order matters? Thanks – georger Jun 29 '18 at 23:15
  • 21
    My understanding is that args passed after the name of the image are directed to the command that is run in the container, and args passed prior to the name of the image are passed to Docker – Brian Jul 12 '18 at 19:13
  • wow...it worked for me. thank you a lot. The example on (looked up 2019may04) on https://docs.docker.com/samples/library/postgres on my mac did not work. Did I miss something? – Dirk Schumacher May 04 '19 at 07:27
14

Run the postgre image with the correct Port Mapping using -p <host_port>:<container_port>:

docker run --same-options-as-step-one -d -p 5432:5432 postgres:9.1
Ali Dehghani
  • 46,221
  • 15
  • 164
  • 151
  • Thanks! I've done that. But still can't connect using psql. port 5432 is not being exposed, or I don't know how to connect. My host's psql program is working properly (I can connect to other hosts, but not to my container) – Jorge Arévalo Mar 11 '16 at 19:00
  • What does `docker port ` display? – Ali Dehghani Mar 11 '16 at 19:05
  • It should print something like `5432/tcp -> 0.0.0.0:5432` – Ali Dehghani Mar 11 '16 at 19:07
  • 5432/tcp -> 0.0.0.0:5432. Tried with -h 0.0.0.0 -p 5432. Getting the connection refused error: Is the server running...? Can I really connect using just plain psql or do I need to run another container to just test psql? Because the official doc doesn't use the normal psql command: https://hub.docker.com/_/postgres/ – Jorge Arévalo Mar 11 '16 at 19:08
  • 2
    You should be able to use plain `psql`.. did you try `-h 127.0.0.1 -p 5432`? – Ali Dehghani Mar 11 '16 at 19:13
  • Your port mappings are fine – Ali Dehghani Mar 11 '16 at 19:13
13

I was able to connect using container IP or host IP, except localhost (127.0.0.1).

To get container id run

docker ps

Find required container id and run

docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_id>

Port must be exposed.

Here is an example of docker-compose.yml which starts two containers postgres and adminer, which is database management tool you can use to connect to postgres:

version: '3'
services:
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
  postgres:
    image: postgres:11.4-alpine
    restart: always
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
Roman_K
  • 131
  • 1
  • 4
12

Your docker host is a virtual machine, which has it's own IP adddres. You can detect this IP address by entering the following command:

docker-machine ip

The answer will be something like 192.168.99.100

When you have mapped the ports using the -p 5432:5432 switch, you will be able to connect to postgres with any tool from your dev machine using the IP address mentioned.

Marcel Posdijk
  • 627
  • 6
  • 6
  • This is the only answer that worked for me. Looks like if a virtual machine is present, Docker maps ports to this machine rather than host system. – Alexander Mar 25 '20 at 16:44
7

I had a similar issue. My problem was simply 0.0.0.0 not mapping to localhost so I just had to add to psql

psql --host=0.0.0.0

This is presuming

docker port <container name>

outputs

5432/tcp -> 0.0.0.0:5432
Alex Spera
  • 741
  • 7
  • 3
2

Other answers work, but don't explain why they work.

Given the command:

psql -h localhost -p 5432:5432 -U postgres

localhost is actually a special value that tells psql to look for a unix socket connection, instead of going over TCP. We can't use unix sockets to connect to docker services.

Changing the command like so fixes it, by forcing TCP:

psql -h 127.0.0.1 -p 5432:5432 -U postgres

That will work as long as you docker run ... -p 5432:5432 .... Specifying the IP returned by docker-machine ip also forces TCP, so that also works.

whitehat101
  • 2,428
  • 23
  • 18
1

I had a similar problem working in a VMWare virtual machine with Lubuntu. The VM had been paused and then was restarted. The PostgreSQL Docker container was correctly mapped and listening on localhost:5432, but I always got:

psql: server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.

Restarting the VM solved the problem in my case.

Michael
  • 111
  • 1
  • 5
1

Try this to install postgresql

 docker run --name postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=fred postgres:alpine

Or Change port host machine Heree (mac)

 docker run --name postgres -d -p 5436:5432 -e POSTGRES_PASSWORD=fred postgres:alpine

enter image description here

Tip: Install pgadmin4

docker run -p 5050:80  -e "PGADMIN_DEFAULT_EMAIL=name@example.com" -e "PGADMIN_DEFAULT_PASSWORD=admin"  -d dpage/pgadmin4

enter image description here

lava
  • 6,020
  • 2
  • 31
  • 28
0

People who want to implement this code for containerized database use and people who want to use graphical interface can also use this

  • docker run -d -p 5432:5432 --name postgres -e POSTGRES_PASSWORD=root -d postgres

  • docker ps

  • docker inspect

  • result: "IPAddress": "172.17.0.2",

  • docker run -p 5050:80 -e "PGADMIN_DEFAULT_EMAIL=name@example.com" -e "PGADMIN_DEFAULT_PASSWORD=admin" -d dpage/pgadmin4

  • http://localhost:5432/

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
0

It's 2023 and I just had a similar problem. I'm using Colima, and restarting it resolved the issue. It might be due to it running for an extended period of time.