Docker postgres image: How to restrict access from host network?

Viewed 415

I'm running a postgres server in a docker container within a custom docker network, and I found I can access it using psql from the host.

This seems to me to be undesirable from a security perspective since I thought the point of docker networks was to isolate access to the containers.

My thinking was that I would run my app in a separate container within the same docker network and publish ports on the app container only. That way, the app can be accessed from the outside world, but the database can't be.

My question is: Why is the 5432 port being published to host on the postgres container without me explicitly specifying that, and how can I "unpublish" this port?

And a related question would be: am I wrong that publishing port 5432 is a security concern in this case (or at least less secure than not publishing it)?

My container is running the official docker postgres image here: https://hub.docker.com/_/postgres/

Thanks for any help!

Edit: Here is the docker command I'm using to run the container:

docker run -d --restart=always --name=db.geppapp.com -e "POSTGRES_USER=<user>" -e "POSTGRES_PASSWORD=<password>" -e "POSTGRES_DB=gepp" -v "/mnt/storage/postgres-data:/var/lib/postgresql/data" --net=db postgres

Edit 2: My original question was not entirely correct as docker was not in fact publishing the port 5432 to the host but rather I was specifying the container's IP address as the host when connecting to postgres with psql as follows:

psql --host=<docker-assigned-ip> --username=<user> --dbname=gepp

So the thing preventing me from restricting access to the container from the host is in fact that an IP address is assigned to the container on the host network.

2 Answers

The Dockerfile of postgres exposes that port 5432, but that does not mean it makes the port of the container accessible to the host. To expose the port to host, you must use either the -p flag to publish a range of ports or the -P flag to publish all of the exposed ports. But I don't see that in your command.

Are you sure you are not accessing a local postgres and not the container postgres?

or Are you connected to the Host network? If docker container is set to network_mode: host or type of host, any port exposed in the container would be exposed on the docker host as well, without requiring the -p or -P docker run options.

Thanks everyone who commented and answered. I'm answering my own question with a summary of my best understanding based on the replies and other things I've read.

As I mentioned in the edit to my question the thing preventing me from restricting access to the container from the host is the IP assignment on the host network.

According to the docker docs: (https://docs.docker.com/config/containers/container-networking/)

By default, the container is assigned an IP address for every Docker network it connects to.

In this case, the container is not technically "connected" to the host network but has an IP on that network anyway. David pointed out in comments that this only occurs on Linux, not on Windows or Mac (I haven't personally verified this).

So it would appear that due to the way docker networks are implemented in Docker Linux, an IP address is published to the host for all running containers, and there's no way to prevent this.

From a security perspective, since the docker host is always trusted, my understanding is that database security comes mainly from restricting access to the host itself (network and linux account security), and the native database credential security. Docker does not add another secure layer as I was initially thinking it might.

Related