Skip to content

Support multiple domains #1

@konard

Description

@konard

Deploying Docker Services with Traefik for Multiple Domains

This guide explains how to configure Docker Compose with Traefik to expose services on multiple domains, automatically generating TLS certificates via Let's Encrypt.


1. Overview

We want:

  • chatgpt_proxy_prod accessible via:
    • api.domain1.com
    • api.domain2.com
  • desktop (Portainer) accessible via:
    • desktop.domain1.com
    • desktop.domain2.com
  • Automatic HTTPS via Traefik ACME.
  • Configuration without hardcoding sensitive values in Compose.

2. Environment Variables

Create a .env file in the same folder as your docker-compose.prod.yml:

# Base domains
HOST1=domain1.com
HOST2=domain2.com

# Email for Let's Encrypt
EMAIL=admin@domain1.com

Docker Compose automatically loads .env and replaces ${VAR} in the YAML.


3. docker-compose.prod.yml

version: '3.9'

services:
  chatgpt_proxy_prod:
    build: .
    container_name: chatgpt_proxy_prod
    volumes:
      - ./src/db:/usr/src/app/src/db
    environment:
      - PORT=8088
      # ... your other environment variables ...
    restart: unless-stopped
    labels:
      - "traefik.enable=true"

      # Router for first domain
      - "traefik.http.routers.chatgpt1.rule=Host(`api.${HOST1}`)"
      - "traefik.http.routers.chatgpt1.entrypoints=websecure"
      - "traefik.http.routers.chatgpt1.tls.certresolver=myresolver"
      - "traefik.http.routers.chatgpt1.service=chatgpt_proxy_prod"

      # Router for second domain
      - "traefik.http.routers.chatgpt2.rule=Host(`api.${HOST2}`)"
      - "traefik.http.routers.chatgpt2.entrypoints=websecure"
      - "traefik.http.routers.chatgpt2.tls.certresolver=myresolver"
      - "traefik.http.routers.chatgpt2.service=chatgpt_proxy_prod"

      # Service port
      - "traefik.http.services.chatgpt_proxy_prod.loadbalancer.server.port=8088"

    networks:
      - trfk

  desktop:
    image: portainer/portainer-ce:latest
    container_name: "desktop"
    restart: unless-stopped
    volumes:
      - "desktop_volume:/data"
      - "/var/run/docker.sock:/var/run/docker.sock"
    labels:
      - "traefik.enable=true"

      # Router for first domain
      - "traefik.http.routers.desktop1.rule=Host(`desktop.${HOST1}`)"
      - "traefik.http.routers.desktop1.entrypoints=websecure"
      - "traefik.http.routers.desktop1.tls.certresolver=myresolver"
      - "traefik.http.routers.desktop1.service=desktop"

      # Router for second domain
      - "traefik.http.routers.desktop2.rule=Host(`desktop.${HOST2}`)"
      - "traefik.http.routers.desktop2.entrypoints=websecure"
      - "traefik.http.routers.desktop2.tls.certresolver=myresolver"
      - "traefik.http.routers.desktop2.service=desktop"

      # Service port
      - "traefik.http.services.desktop.loadbalancer.server.port=9008"

    networks:
      - trfk

  traefik:
    image: traefik:v2.9
    container_name: traefik-prod
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--api.dashboard=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--log.level=DEBUG"
      - "--certificatesresolvers.myresolver.acme.email=${EMAIL}"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.${HOST1}`)"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.service=api@internal"
    ports:
      - "88:88"
      - "443:443"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    networks:
      - trfk

networks:
  trfk:
    driver: overlay
    external: true

volumes:
  desktop_volume:

4. How it works

  1. Traefik watches Docker for containers with the label traefik.enable=true.
  2. Each Host(...) router tells Traefik which domains to route to which service.
  3. The tls.certresolver=myresolver instructs Traefik to request Let's Encrypt certificates automatically.
  4. Using multiple routers (chatgpt1, chatgpt2) allows the same container to serve multiple domains.
  5. Using .env makes it easy to add or change domains without editing the Compose file.

5. Notes

  • Ensure both HOST1 and HOST2 point via DNS to your server IP.
  • Ports 80 and 443 must be accessible for TLS challenge.
  • You can add more domains by adding more routers (e.g., chatgpt3, desktop3).

This setup allows multiple base domains with autogenerated certificates and keeps the configuration maintainable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions