0

I was recently shocked to find out that docker writes its own iptables rules and ignores ufw bindings completely. I had blocked all ports using the ufw deny incoming command and then selectively allowed only the ports that I wanted to expose.

I have a very simple setup that utilizes a postgresql container and a simple nodejs application. My primary goal is to keep the postgresql container port off the internet but let the node backend accept requests through port 3333. How do I do that?

My current docker-compose.yml file looks like this:

version: "3"

services:
  redis:
    image: redis:latest
    ports:
      - 6379:6379
    command: ["redis-server", "/redis.conf"]
    network_mode: host
  database:
    image: "postgres"
    env_file:
      - ./database/database.env
    volumes:
      - database-data:/var/lib/postgresql/data
      - ./database/init-db.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - 5432:5432
    restart: always
    network_mode: host

  backend:
    depends_on: [database]
    build: ./server
    volumes:
      - ./files:/var/lib/files
    ports:
      - 3333:3333
    restart: always
    network_mode: host

volumes:
  database-data:
1
  • typically you put all your boxes inside a private network where they have zero incoming access from the outside world ( internet ) unless specified by your reverse proxy server ( haproxy or nginx ) yet have full access to and from each other ... aws VPC gives you this so does other private network toolings – Scott Stensland Apr 26 at 21:23
1

When you use network_mode host, the published ports are ignored, which means the ports that are open in the containers will be the same port in the host. Does not matter what you had declared in ports

The default behavior is every service in the compose can talk to each other.

Links are not required to enable services to communicate - by default, any service can reach any other service at that service’s name

let's use this simple compose as an example. There is no network defined, docker will create one.

version: '3.7'
services:
  nginx1:
    image: nginx
    ports:
      - '8080:80'
  nginx2:
    image: nginx

Nginx1 will be reachable through port 8080 on localhost and any other machines in the network.

$ curl -I http://localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.19.10

While nginx2 will even have a port on the host.

$ docker-compose ps
      Name                     Command               State                  Ports                
-------------------------------------------------------------------------------------------------
nginx1_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8080->80/tcp,:::8080->80/tcp
nginx2_1   /docker-entrypoint.sh ngin ...   Up      80/tcp                              

And they still reach each other by their internal port using the service name

Accessing nginx1 from nginx2

$ docker exec -it nginx2_1 curl -I http://nginx1:80
HTTP/1.1 200 OK
Server: nginx/1.19.10

Accessing nginx2 from nginx1

$ docker exec -it nginx1_1 curl -I http://nginx2:80
HTTP/1.1 200 OK
Server: nginx/1.19.10
0

If you're looking to access your database only from localhost, you can do something like that:

    ports:
      - "127.0.0.1:5432:5432"
0

Instead of using network_mode to host, you can simply make use of links (new versions uses networks) which will make the communication to happen between two containers.

I have updated the docker-compose.yaml file and added links to connect database service (database container) to be accessed from your backend service.

In your backend database configuration, you need to use database as the db host. (Here database is the service name which is defined in the compose.yaml file)

version: "3"

services:
  redis:
    image: redis:latest
    ports:
      - 6379:6379
    command: ["redis-server", "/redis.conf"]
  database:
    image: "postgres"
    env_file:
      - ./database/database.env
    volumes:
      - database-data:/var/lib/postgresql/data
      - ./database/init-db.sql:/docker-entrypoint-initdb.d/init.sql
    restart: always
  backend:
    depends_on: [database]
    build: ./server
    volumes:
      - ./files:/var/lib/files
    ports:
      - 3333:3333
    restart: always
    links:
      - "database"

volumes:
  database-data:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.