Forward http(s) to postgresql container in docker swarm/compose possible?

Hi,
Im woring in a strict environment and I have access to the postgresql machine only via http/https.
On this postgresql machine I would run 2 parallel environments with docker compose.
Is there a possibility to forward the http/https to the postgres container on 5432?
The other problem is , the postgres is in the non-external network. So is my scenario possible?

Here is my try

Traefik config

EntryPoints:
  web:
    address: :80
    # (Optional) Redirect to HTTPS
    # ---
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: :443

And the compose config for traefik

version: '3.7'
services:

  reverse-proxy:
    container_name: traefik

    # The official v2 Traefik docker image
    image: traefik:v2.8
    ports:
      # The HTTP port
      - "80:80"
      - "443:443"
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
      - /docker/traefik/config:/etc/traefik
      - /docker/traefik/certs/:/etc/traefik/certs
      - /docker/traefik/log/:/var/log/traefik

    networks:
      - proxy

    restart: always

networks:
  proxy:
    name: proxy

Compose for Postgres

version: "3.7"
services: 
  db:
    image: postgres:14

    environment:
      - POSTGRES_DB=mydb
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    networks:
      - private-network
    labels:      
      traefik.enable: 'true'      
      traefik.http.routers.dev-db.rule: Host(`myhost-name`)      
      traefik.http.routers.dev-db.entrypoints: websecure  
      traefik.http.routers.dev-db.service: dev-db     
      traefik.http.services.dev-db.loadbalancer.server.port: "5432"
      traefik.docker.network: "proxy"
    restart: always
    
networks:  
  proxy:    
    name: proxy    
    external: true
  private-network:
    name: private-network

Postgres might use TLS, but pretty sure it does not use http, so you would need to use a TCP router.

Hello, thank you for your quick answer. I will move forward with the tcp.

One remaining question what I have

is

traefik.docker.network: "proxy"

the way to expose the 5432 from non-traefik network via traefik? because my postgres will sit in the non-proxy network

Traefik and target service should use the same Docker network, as Traefik Docker Configuration Discovery (with labels) is using the Docker network IPs.

You explicitly need to state the network when your target uses multiple networks and only one is shared with Traefik.

If your target service is not in a Docker network, then you need to set the service with loadbalancer.servers.url. This can’t be done with labels, but you need a separate dynamic config file, loaded via provider.file in static config.

My postgres service also in the docker network.
In my example above my docker compose has 2 networks.

  1. Proxy-network - Traefik sitting in that
  2. Private-network - Postgresql sitting in that with some other containers what not mentioned in my example.
    So I want only expose the Postgresql:5432 from Private-network via the Traefik what is in the Proxy-network.
    All of them in the docker-compose.

So the easy way is to add the proxy network also to my postgresql networks?

Yes, if you want Postgres to be reachable by Traefik, you need to add the proxy network, too. Then Postgres has 2 networks, you need to add docker.network in static or dynamic (labels) config for Traefik.

1 Like

I set the changes. I think everything is good but I can not reach the postgres
Extended the config

EntryPoints:
  web:
    address: :80
    # (Optional) Redirect to HTTPS
    # ---
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: :443
  postgres-db:
    address: :5432

Changed the compose traefik


version: '3.7'
services:

  reverse-proxy:
    container_name: traefik

    # The official v2 Traefik docker image
    image: traefik:v2.8
    ports:
      # The HTTP port
      - "80:80"
      - "443:443"
      - "5432:5432"
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
      - /docker/traefik/config:/etc/traefik
      - /docker/traefik/certs/:/etc/traefik/certs
      - /docker/traefik/log/:/var/log/traefik

    networks:
      - proxy

    restart: always

networks:
  proxy:
    name: proxy

And ofcourse changed the labels and the network
version: "3.7"
services:
db:
image: postgres:14

environment:
  - POSTGRES_DB=mydb
  - POSTGRES_USER=postgres
  - POSTGRES_PASSWORD=postgres
networks:
  - private-network
  - proxy
labels:      
  traefik.enable: 'true'      
  traefik.docker.network: "proxy"
  traefik.tcp.routers.dev-db.rule: HostSNI(`myhost-name`)      
  traefik.tcp.routers.dev-db.entrypoints: postgres-db
  traefik.tcp.routers.dev-db.service: dev-db   
  traefik.tcp.routers.dev-db.tls: "true"     
  traefik.tcp.services.dev-db.loadbalancer.server.port: "5432"

restart: always

networks:
proxy:
name: proxy
external: true
private-network:
name: private-network

I have no idea where is the error. I set the logs to debug but doesnt help. It goes to timeout

Do you know what you are doing? Does Postgres support TLS? Is your client set up to use TLS? Is your DB set up to use TLS? Will it create a custom certificate?

If you have not loaded custom TLS certs in Traefik using tls: true, Traefik will create custom certs which your client will probably not trust. For a trusted cert you would need paid certs, LetsEncrypt or import the custom certs on client side.

I would just remove that line and have a plain TCP/IP connection proxied from the client to your DB, without Traefik interfering with TLS. Let client and DB do the encryption, make sure it is enabled.

Note that you then need to use HostSNI(`*`), as Traefik can not look inside a TLS connection without having the cert available.

Hello,
Yes I know. I wont say I'm an expert but thatswhy Im here :slight_smile:

Postgresql uses TLS.
I have a trusted ,payed certificate what im using in Traefik.
So this should not be the problem.
HostSNI(*) is not an option because I would use multiple postgresql on the machine behind traefik connected to different domain names.

I don’t know how Postgres handles TLS. You can try to use your paid certs with Postgres, too, and use tls.passthrough=true. Or let Postgres create its own proprietary cert and use insecureSkipVerify: true on global or service level.

still not working.
if I put the

tls.passthrough: false
HostSNI(`*`)
tls: false

it works but if I switch one of that to true or define a hostname its not working.

I set the
insecureSkipVerify: true also.

But the postrgresql is running with TLS because If I connect with the Traefik setup above I can make the SSL connection.

psql (14.8 (Ubuntu 14.8-0ubuntu0.22.04.1), server 14.7 (Debian 14.7-1.pgdg110+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.

Any idea?

I was thinking to reach the following scenario. This is exactly what I would do but on the same machine with docker-compose and traefik