Docker compose with Treafik and portainer + redirect and LetsEnCrypt

Hello guys I want to try Docker with treafik and portainer.

in a second step, Zammad and Akeneo are to be added.

I've already done the following:

  • Treafik is running
  • Portainer is running
  • Treafik accepts URL's and encrypts them with LetsEnCrypt but tw then refer to 404 pages
  • Redirect from http to https takes place.

What's not yet:

  • Portainer via the URL and with port 9000 refers to 404 and not to portainer.
  • Access to portainers is not seen in tobacco shops. I think the network is missing here and I still don't know how to best approach it.
  • What would be even more important to me that Treafik would be encrypted with a password.

Here is my docker-compose.yaml file

version: "3.3"

services:

  traefik:
    image: "traefik:latest"
    container_name: "Traefik"
    command:
#     - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
#     - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=infos@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    labels:
      - "traefik.enable=true"
      # Routers
      - "traefik.http.routers.whoami.rule=Host(`traefik.example.com`)"
        # global redirect to https
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"
      - "traefik.http.routers.traefik.middlewares=traefik-auth"
      # Middleware
      - "traefik.http.middlewares.traefik-auth.basicauth.removeheader=true"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
        # middleware redirect
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

  portainer:
    image: "portainer/portainer"
    container_name: "Portainer"
    command: -H unix:///var/run/docker.sock
    restart: always
    ports:
      - "9000:9000"
      - "8000:8000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "portainer_data:/data"
    labels:
      - "traefik.enable=true"
      # Routers
      - "traefik.http.routers.whoami.rule=Host(`portainer.example.com`)"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"

volumes:
  portainer_data:

Hello,

version: "3.3"

services:

  traefik:
    image: traefik:v2.1.6
    container_name: Traefik
    command:
      - "--log.level=INFO"
      - "--api"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=infos@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./letsencrypt:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro
    labels:
      traefik.enable: true

      # Routers
      traefik.http.routers.traefik.rule: Host(`traefik.example.com`)
      traefik.http.routers.traefik.entrypoints: websecure
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.tls.certresolver: myresolver
      traefik.http.routers.traefik.middlewares: traefik-auth

      # global redirect to https
      traefik.http.routers.http-catchall.rule: hostregexp(`{host:.+}`)
      traefik.http.routers.http-catchall.entrypoints: web
      traefik.http.routers.http-catchall.middlewares: redirect-to-https
      
      # Middleware
      traefik.http.middlewares.traefik-auth.basicauth.removeheader: true
      traefik.http.middlewares.traefik-auth.basicauth.users: test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0
      # middleware redirect
      traefik.http.middlewares.redirect-to-https.redirectscheme.scheme: https

  portainer:
    image: portainer/portainer
    container_name: Portainer
    command: -H unix:///var/run/docker.sock
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    labels:
      traefik.enable: true

      traefik.http.routers.portainer.rule: Host(`portainer.example.com`)
      traefik.http.routers.portainer.entrypoints: websecure
      traefik.http.routers.portainer.tls.certresolver: myresolver
      traefik.http.routers.portainer.service: portainer_svc

      traefik.http.services.portainer_svc.loadBalancer.server.port: 9000

volumes:
  portainer_data:

thanks @Idez my problem is solved now i can move on to the next step

Yesterday I noticed that Portainer does not generate the LetsEncrypt.

I first declared an exception in the browser and after removing it, I now see the warning.

What can that be?

In the Logs i found these Error:

Traefik                 | time="2020-03-03T09:18:00Z" level=error msg="the router traefik@docker uses a non-existent resolver: myresolver"
Traefik                 | time="2020-03-03T09:18:00Z" level=error msg="the router zammad-nginx@docker uses a non-existent resolver: myresolver"
Traefik                 | time="2020-03-03T09:18:00Z" level=error msg="the router portainer@docker uses a non-existent resolver: myresolver"

Ok I looked again:
All 3 domains or subdomains are now displayed with an SSL error.
The domain issuer is: Fake LE Intermediate X1
my config looks like this:

version: "3.3"

services:

  traefik:
    image: traefik:v2.1
    container_name: Traefik
    command:
      - "--log.level=INFO"
      - "--api"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=infos@example.de"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./letsencrypt:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro
    labels:
      traefik.enable: true

      # Routers
      traefik.http.routers.traefik.rule: Host(`traefik.example.de`)
      traefik.http.routers.traefik.entrypoints: websecure
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.tls.certresolver: myresolver
      traefik.http.routers.traefik.middlewares: traefik-auth

      # global redirect to https
      traefik.http.routers.http-catchall.rule: hostregexp(`{host:.+}`)
      traefik.http.routers.http-catchall.entrypoints: web
      traefik.http.routers.http-catchall.middlewares: redirect-to-https

      # Middleware
      traefik.http.middlewares.traefik-auth.basicauth.removeheader: true
      traefik.http.middlewares.traefik-auth.basicauth.users: csaeum:$$1$$X[kMyb^l$$Npy/uslnNuMB4pK0focS00

      # middleware redirect
      traefik.http.middlewares.redirect-to-https.redirectscheme.scheme: https

  portainer:
    image: portainer/portainer
    container_name: Portainer
    command: -H unix:///var/run/docker.sock
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    labels:
      traefik.enable: true

      # Routers
      traefik.http.routers.portainer.rule: Host(`portainer.example.de`)
      traefik.http.routers.portainer.entrypoints: websecure
      traefik.http.routers.portainer.tls.certresolver: myresolver
      traefik.http.routers.portainer.service: portainer_svc

      traefik.http.services.portainer_svc.loadBalancer.server.port: 9000

  zammad-backup:
    command: ["zammad-backup"]
    depends_on:
      - zammad-railsserver
    entrypoint: /usr/local/bin/backup.sh
    environment:
      - BACKUP_SLEEP=86400
      - HOLD_DAYS=10
      - POSTGRESQL_USER=${POSTGRES_USER}
      - POSTGRESQL_PASSWORD=${POSTGRES_PASS}
    image: ${IMAGE_REPO}:zammad-postgresql${VERSION}
    links:
      - zammad-postgresql
    restart: ${RESTART}
    volumes:
      - zammad-backup:/var/tmp/zammad
      - zammad-data:/opt/zammad

  zammad-elasticsearch:
    environment:
      - discovery.type=single-node
    image: ${IMAGE_REPO}:zammad-elasticsearch${VERSION}
    restart: ${RESTART}
    volumes:
      - elasticsearch-data:/usr/share/elasticsearch/data

  zammad-init:
    command: ["zammad-init"]
    depends_on:
      - zammad-postgresql
    image: ${IMAGE_REPO}:zammad${VERSION}
    links:
      - zammad-elasticsearch
      - zammad-postgresql
    restart: on-failure
    volumes:
      - zammad-data:/opt/zammad

  zammad-memcached:
    command: memcached -m 256M
    image: memcached:1.5.22-alpine
    restart: ${RESTART}

  zammad-nginx:
    command: ["zammad-nginx"]
    expose:
      - "80"
    depends_on:
      - zammad-railsserver
    image: ${IMAGE_REPO}:zammad${VERSION}
    links:
      - zammad-railsserver
      - zammad-websocket
    restart: ${RESTART}
    volumes:
      - zammad-data:/opt/zammad

  zammad-postgresql:
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASS}
    image: ${IMAGE_REPO}:zammad-postgresql${VERSION}
    restart: ${RESTART}
    volumes:
      - postgresql-data:/var/lib/postgresql/data

  zammad-railsserver:
    command: ["zammad-railsserver"]
    depends_on:
      - zammad-memcached
      - zammad-postgresql
    image: ${IMAGE_REPO}:zammad${VERSION}
    links:
      - zammad-elasticsearch
      - zammad-memcached
      - zammad-postgresql
    restart: ${RESTART}
    volumes:
      - zammad-data:/opt/zammad

  zammad-scheduler:
    command: ["zammad-scheduler"]
    depends_on:
      - zammad-memcached
      - zammad-railsserver
    image: ${IMAGE_REPO}:zammad${VERSION}
    links:
      - zammad-elasticsearch
      - zammad-memcached
      - zammad-postgresql
    restart: ${RESTART}
    volumes:
      - zammad-data:/opt/zammad

  zammad-websocket:
    command: ["zammad-websocket"]
    depends_on:
      - zammad-memcached
      - zammad-railsserver
    image: ${IMAGE_REPO}:zammad${VERSION}
    links:
      - zammad-postgresql
      - zammad-memcached
    restart: ${RESTART}
    volumes:
      - zammad-data:/opt/zammad

volumes:
  portainer_data:
  elasticsearch-data:
    driver: local
  postgresql-data:
    driver: local
  zammad-backup:
    driver: local
  zammad-data:
    driver: local

For Zammad there is still this file
docker-compose.override.yml

version: '3.3'
services:

  zammad-nginx:
    labels:
      traefik.enable: true

      # Routers
      traefik.http.routers.zammad-nginx.rule: Host(`service.example.com`)
      traefik.http.routers.zammad-nginx.entrypoints: websecure
      traefik.http.routers.zammad-nginx.tls.certresolver: myresolver
      traefik.http.routers.zammad-nginx.service: zammad_svc

      traefik.http.services.zammad_svc.loadBalancer.server.port: 80

Ok found the bug.

The problem was the "staging" in the URL:

Here is the line

      - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"

must be changed like this

      - "--certificatesresolvers.myresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"

hello @csaeum, you don't have to mention the lets-encrypt production url. By-default traefik is gonna use production URL only. If u want to use staging lets-encrypt, then we have to add the staging URL in the static configuration(in command section).

comment --certificatesresolvers.myresolver.acme.caserver and traefik still gonna use it.
snippet from https://docs.traefik.io/https/acme/

# CA server to use.
  # Uncomment the line to use Let's Encrypt's staging server,
  # leave commented to go to prod.
  #
  # Optional
  # Default: "https://acme-v02.api.letsencrypt.org/directory"
  #
  # caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"