3

I have created the following docker-compose file...

version: '3'

services:
  db-service:
    image: postgres:11
    volumes:
      - ./db:/var/lib/postgresql/data
    expose: 
      - 5432
    environment:
      - POSTGRES_PASSWORD=mypgpassword
    networks:
      - net1
  pgadmin:
    image: dpage/pgadmin4
    volumes:
      - ./pgadmin:/var/lib/pgadmin
    ports:
      - 5000:80
    environment:
      - PGADMIN_DEFAULT_EMAIL=me@gmail.com
      - PGADMIN_DEFAULT_PASSWORD=mypass
    networks:
      - net1
networks:
  net1:
    external: false

From reading various docs on the docker site, my expectation was that the pgadmin container would be able to access the postgres container via port 5432 but that I should not be able to access postgres directly from the host. However, I am able to use psql to access the database from the host machine.

In fact, if I comment out the expose and ports lines I can still access both containers from the host.

What am I missing about this?

EDIT - I am accessing the container by first running docker container inspect... to get the IP address. For the postgres container I'm using

psql -h xxx.xxx.xxx.xxx -U postgres

It prompts me for the password and then allows me to do all the normal things you would expect.

In the case of the pgadmin container I point my browser to the IP address and get the pgadmin interface.

Note that both of those are being executed from a terminal on the host, not from within either container. I've also commented out the expose command and can still access the postgres db.

dazedandconfused
  • 3,131
  • 1
  • 18
  • 29
  • How are you accessing the containers from the host? What `psql` command are you running? – David Maze Mar 01 '19 at 15:32
  • `EXPOSE` is just documentation. You can start a container without exposing any ports, then "get inside" and start a few daemons on different ports. The host will be able to access them at `container_ip:port`. More info [here](https://stackoverflow.com/questions/22111060/what-is-the-difference-between-expose-and-publish-in-docker/47594352#47594352) – tgogos Mar 01 '19 at 15:44

3 Answers3

4

docker-compose creates a network for those two containers to be able talk to each-other when you run it, through a DNS service which will contain pointers to each service, by name.

So from the perspective of the pgadmin container, the dbserver can be reached under hostname db-service (because that is what you named your service in the docker-compose.yml file).

So, that traffic does not go through the host, as you were assuming, but through the aforementioned network.

For proof, docker exec -it [name-of-pg-admin-container] /bin/sh and type: ping db-service. You will see that docker provides a DNS resolution and that you can even open a connection to the normal postgres port there.

Hans Westerbeek
  • 5,645
  • 3
  • 34
  • 35
0

The containers connect one with another by bridge network net1.

When you expose port, you create port forwarding in your IPTABLES for connecting host network and net1.

Stop expose 5432 port in your db-service and you see that you can't connect from your host to db-service.

ozlevka
  • 1,988
  • 16
  • 28
0

Docker assigns an internal IP address to each container. If you happen to have this address, and it happens to be reachable, then Docker doesn’t do anything specific to firewall it off. On a Linux host in particular, if specific Docker network is on 172.17.0.0/24, the host might have a 172.17.0.1 address and a specific container might be 172.17.0.2, and they can talk to each other this way.

Using the Docker-internal IP addresses is not a best practice. If you ever delete and recreate a container, its IP address will change; on some host platforms you can’t directly access the private IP addresses even from the same host; the private IP addresses are never reachable from other hosts. In routine use you should never need to docker inspect a container.

The important level of isolation you do get here is that the container isn’t accessible from other hosts unless you explicitly publish a port (docker run -p option, Docker Compose ports: option). The setup here is much more uniform than for standard applications: set up the application inside the container to listen on 0.0.0.0 (“all host interfaces”, usually the default), and then publish a port or not as your needs require. If the host has multiple interfaces you can publish a port on only one of them (even if the application doesn’t natively support that).

David Maze
  • 130,717
  • 29
  • 175
  • 215