Help with making a subdomain proxy for a port

Hi All,

I've been reading the tutorials and topics on this forum, but after being at this for 2 days I haven't been able to accomplish the relatively simple task of making a subdomain proxy for a port. What I intend to do is to run a few node.js apps and a few containers on my server (a vps on Digitalocean), and have Traefik proxy them with subdomains. I'm currently testing out a subdomain proxy with a portainer instance that I have installed before Traefik. This is my current docker-compose.yml for Traefik:

version: '3.8'

services:
  reverse-proxy:
    image: traefik:v2.10
    command:
      - --providers.docker
      - --api.insecure=false
      - --api.dashboard=true
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.letsencrypt.acme.tlschallenge=true
      - --certificatesresolvers.letsencrypt.acme.email=<my email here>
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - letsencrypt:/letsencrypt
    labels:

      - "traefik.http.routers.test1.rule=Host(`test1.mydomain.com`)"
      - "traefik.http.routers.test1.middlewares=redirect-to-google"
      - "traefik.http.middlewares.redirect-to-google.redirectregex.regex=^http://test1\\.mydomain\\.com/(.*)"
      - "traefik.http.middlewares.redirect-to-google.redirectregex.replacement=https://google.com/$${1}"

      - "traefik.http.routers.portainer.rule=Host(`portainer.mydomain.com`)"
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.service=portainer"
      - "traefik.http.services.portainer.loadbalancer.server.port=9443"
      - "traefik.http.services.portainer.loadbalancer.server.scheme=http"

      - "traefik.http.routers.mydomain.rule=Host(`mydomain.com`)"
      - "traefik.http.routers.mydomain.middlewares=redirect-to-netlify"
      - "traefik.http.middlewares.redirect-to-netlify.redirectregex.regex=^http://mydomain\\.com/(.*)"
      - "traefik.http.middlewares.redirect-to-netlify.redirectregex.replacement=https://mynetlifyapp.netlify.app/$${1}"

      - "traefik.http.routers.mydomain-secure.rule=Host(`mydomain.com`)"
      - "traefik.http.routers.mydomain-secure.entrypoints=websecure"
      - "traefik.http.routers.mydomain-secure.middlewares=redirect-to-netlify-secure"
      - "traefik.http.middlewares.redirect-to-netlify-secure.redirectscheme.scheme=https"

      - "traefik.enable=true"
  whoami:
    # A container that exposes an API to show its IP address
    image: traefik/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls=true"
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
      - "traefik.http.routers.whoami.middlewares=whoami-redirect-secure"
      - "traefik.http.middlewares.whoami-redirect-secure.redirectscheme.scheme=https"

networks:
  traefik-proxy_default:
    external: true

volumes:
  letsencrypt:
    external: false

From the above:

  • test1.mydomain.com successfully redirects to https://google.com/
  • mydomain.com successfully redirects to https://mynetlifyapp.netlify.app/
  • whoami.mydomain.com successfully displays the server information, and http requests are redirected to https.
  • portainer.mydomain.com however, returns a 404, no matter if i access it via http or https. (edit) But Portainer works well independently at https://myipaddress:9443, no matter if I have Traefik set up or not.

I've read a few topics on this forum and it seems like the configuration should work. Can anyone guide me as to what I'm missing out on? I'm trying not to setup another container service in this docker-compose file and proxy them from there as some of my node.js apps are not containerized.

The labels need to go on the target service/container, compare to simple Traefik example.

If your target is an external URL, so not Docker discoverable by Traefik, then you need to create a dynamic config file with loadbalancer.servers.url and load it via providers.file in static config.

@bluepuma77 thanks for the reply and the example! I took a look at your file and managed to get my other docker services proxied properly.

I still can't seem to get it to work with services that are not Docker discoverable though. This is what I was thinking might work for a portainer container served over port 9443 (via https) on the same VPS:

- traefik.http.routers.myportainer.rule=Host(`portainer.example.com`)
- traefik.http.routers.myportainer.service=portainer
- traefik.http.services.portainer.loadbalancer.server.port=9443

But, when checking the destination it is directed to in the Traefik dashboard, I'm getting a totally different IP address as compared to the VPS my services are hosted on. Any ideas why?

I thought I explained that:

How should Traefik know the IP of the target service/container? It’s using the dedicated (internal) Docker IPs when using Configuration Discovery.

You need to create a dynamic config file with router and service (doc).

Alright, so I added a few lines to the previous docker-compose.yml file to set up the dynamic config:

volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt
      - /home/traefik-config/dynamic:/home/traefik-config/dynamic

command:
  - --providers.file.directory=/home/traefik-config/dynamic
  - --providers.file.watch=true

I then created the dynamic config file using the config from the doc you linked, and added a connection to the traefik dashboard as well just to test it:

# http routing section
http:
  routers:
    # Define a connection between requests and services
    to-whoami:
      rule: "Host(`example.com`) && PathPrefix(`/whoami/`)"
      # If the rule matches, applies the middleware
      middlewares:
        - test-user
      # If the rule matches, forward to the whoami service (declared below)
      service: whoami

    # define a connection to traefik dashboard at traefik.example.com
    traefik-dashboard:
      rule: "Host(`traefik.example.com`)"
      service: api@internal
      middlewares:
        - test-user

  middlewares:
    # Define an authentication mechanism
    test-user:
      basicAuth:
        users:
          - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/

  services:
    # Define how to reach an existing service on our infrastructure
    whoami:
      loadBalancer:
        servers:
          - url: http://whoami-service

The logs for Traefik don't show any errors when loading the config file, but none of the connections specified in this config file now work, they all lead to "ERR_CONNECTION_RESET". I thought it was an issue with my config file somehow, but through some trial and error it seems Traefik is indeed reading the right config file. Any idea why this wouldn't work?

Again, really appreciate the help you're providing here - server administration isn't my main job, but I have to do this as a freelancer who wants to run their own services.

traefik.example.com needs to exist and point to the IP of your Traefik instance. It uses special api@internal service, which needs to be enabled. You can leave this as labels when providers.docker is used.

example.com needs to have the same IP. And your service needs to be available at whoami-service, which will be looked up for the IP. Did you register that? You can also use http://<ip>[:<port>] as URL.