I need help setting up a custom api in a docker-compose

Hey everyone,

my problem is that I'm getting a 404 Error when I'm trying to connect to [HOSTNAME]/api. I'm aware that the custom api connection might collide with the internal@api, but I'm not really sure about this, since both services are running on different ports.

Thanks in advance!!

Here is my docker-compose.yml:

version: '3.5'
services:
  traefik:
    image: traefik
    restart: always
    network_mode: host
    env_file:
      - .env
    command:
      - --providers.docker
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=web
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --api.insecure
      - --certificatesresolvers.le.acme.email=${LETSENCRYPT_MAIL}
      - --certificatesresolvers.le.acme.storage=/etc/ssl/certs/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.api.service=api@internal
      - traefik.http.routers.api.rule=Host(`${DOMAIN_NAME}`)
      - traefik.http.routers.traefik.tls.certresolver=le
      - traefik.http.routers.traefik.entrypoints=websecure
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/ssl/certs:/etc/ssl/certs
      - /etc/traefik/traefik.log:/etc/traefik/traefik.log

  db:
    image: postgres
    restart: always
    ports:
      - 5432:5432
    env_file:
      - .env
    volumes:
      - ./api/db/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - internal

  detactive_api:
    build: api
    restart: always
    env_file:
      - .env
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.api.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/api`)
      - traefik.http.services.api.loadbalancer.server.port=80
      - traefik.http.routers.api.tls.certresolver=le
      - traefik.http.routers.api.entrypoints=websecure
    depends_on:
      - db
    networks:
      - web
      - internal

networks:
  web:
    external: true
  internal:
    external: false

Here is the Dockerfile of the api build itself:

FROM rust:latest as build

RUN USER=root cargo new --bin detactive-api
WORKDIR /detactive-api

COPY ./Cargo.lock ./Cargo.lock
COPY ./Cargo.toml ./Cargo.toml

RUN cargo build --release
RUN rm src/*.rs

COPY ./src ./src
COPY ./db ./db

RUN rm ./target/release/deps/detactive_api*
RUN cargo build --release

FROM rust:latest

COPY --from=build /detactive-api/target/release/detactive-api .

CMD ["./detactive-api"]

And here is the entrypoint of the api:

mod routes;
mod types;
mod utils;

use std::net::SocketAddr;

use crate::{routes::api, utils::cors};
use axum::{routing::get, Router};

async fn root() -> String {
    return format!("Detactive API v{}", env!("CARGO_PKG_VERSION"));
}

#[tokio::main]
async fn main() {
    println!("Detactive API v{}", env!("CARGO_PKG_VERSION"));

    let addr = SocketAddr::from(([0, 0, 0, 0], 80));
    let app = Router::new()
        .nest(
            &format!("/v{}", &env!("CARGO_PKG_VERSION")[..1]),
            api().await,
        )
        .route("/", get(root))
        .layer(cors());

    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

I would start by setting those to true or false.

1 Like

Thank you for the hint. :blush: Unfortunately this did not resolve the 404 error.

Config seems okay, are you using https?

Check Traefik debug log and the Traefik dashboard on http://domain:8080/dashboard/, when using

--api.dashboard=true 
--api.insecure=true
1 Like

Yep, I'm using https, but https works fine on root and the /api route.

Regarding the Dashboard, they're no errors/warnings.
Also I don't get any logs from traefik.

Here is my updated docker-compose.yml for the logging config:

version: '3.5'
services:
  traefik:
    image: traefik
    restart: always
    network_mode: host
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=web
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --api.insecure=true
      - --certificatesresolvers.le.acme.email=${LETSENCRYPT_MAIL}
      - --certificatesresolvers.le.acme.storage=/etc/ssl/certs/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
      - --log.level=DEBUG
      - --log.filePath=/etc/traefik/traefik.log
      - --log.format=json
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.api.service=api@internal
      - traefik.http.routers.api.rule=Host(`${DOMAIN_NAME}`)
      - traefik.http.routers.traefik.tls.certresolver=le
      - traefik.http.routers.traefik.entrypoints=websecure
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/ssl/certs:/etc/ssl/certs
      - /etc/traefik:/etc/traefik

  db:
    image: postgres
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - ./api/db/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - internal

  detactive_api:
    build: api
    restart: always
    environment:
      - DETACTIVE_DB_URL=${DETACTIVE_DB_URL}
      - STICKER_DB_URL=${STICKER_DB_URL}
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.api.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/api`)
      - traefik.http.services.api.loadbalancer.server.port=80
      - traefik.http.routers.api.tls.certresolver=le
      - traefik.http.routers.api.entrypoints=websecure
    depends_on:
      - db
    networks:
      - web
      - internal

networks:
  web:
    external: true
  internal:
    external: false

Your logs should be written to the file, inside and outside of your container.

Make sure to use the Traefik image with a current version number.

1 Like

I'm using Traefik v2.10.1 and the /etc/traefik/traefik.log looks like this:

[I replaced the hostname with "exampleapp"]

cat traefik.log
{"level":"info","msg":"Traefik version 2.10.1 built on 2023-04-27T14:52:35Z","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"Static configuration loaded {\"global\":{\"checkNewVersion\":true},\"serversTransport\":{\"maxIdleConnsPerHost\":200},\"entryPoints\":{\"traefik\":{\"address\":\":8080\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":\"10s\"},\"respondingTimeouts\":{\"idleTimeout\":\"3m0s\"}},\"forwardedHeaders\":{},\"http\":{},\"http2\":{\"maxConcurrentStreams\":250},\"udp\":{\"timeout\":\"3s\"}},\"web\":{\"address\":\":80\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":\"10s\"},\"respondingTimeouts\":{\"idleTimeout\":\"3m0s\"}},\"forwardedHeaders\":{},\"http\":{},\"http2\":{\"maxConcurrentStreams\":250},\"udp\":{\"timeout\":\"3s\"}},\"websecure\":{\"address\":\":443\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":\"10s\"},\"respondingTimeouts\":{\"idleTimeout\":\"3m0s\"}},\"forwardedHeaders\":{},\"http\":{},\"http2\":{\"maxConcurrentStreams\":250},\"udp\":{\"timeout\":\"3s\"}}},\"providers\":{\"providersThrottleDuration\":\"2s\",\"docker\":{\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"network\":\"web\",\"swarmModeRefreshSeconds\":\"15s\"}},\"api\":{\"insecure\":true,\"dashboard\":true},\"log\":{\"level\":\"DEBUG\",\"filePath\":\"/etc/traefik/traefik.log\",\"format\":\"json\"},\"certificatesResolvers\":{\"le\":{\"acme\":{\"email\":\"exampleapp.app@gmail.com\",\"caServer\":\"https://acme-v02.api.letsencrypt.org/directory\",\"storage\":\"/etc/ssl/certs/acme.json\",\"keyType\":\"RSA4096\",\"certificatesDuration\":2160,\"tlsChallenge\":{}}}}}","time":"2023-05-11T14:49:37Z"}
{"level":"info","msg":"\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://doc.traefik.io/traefik/contributing/data-collection/\n","time":"2023-05-11T14:49:37Z"}
{"level":"info","msg":"Starting provider aggregator aggregator.ProviderAggregator","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"web","level":"debug","msg":"Starting TCP Server","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"websecure","level":"debug","msg":"Starting TCP Server","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","msg":"Starting TCP Server","time":"2023-05-11T14:49:37Z"}
{"level":"info","msg":"Starting provider *traefik.Provider","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"*traefik.Provider provider configuration: {}","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"Configuration received: {\"http\":{\"routers\":{\"api\":{\"entryPoints\":[\"traefik\"],\"service\":\"api@internal\",\"rule\":\"PathPrefix(`/api`)\",\"priority\":2147483646},\"dashboard\":{\"entryPoints\":[\"traefik\"],\"middlewares\":[\"dashboard_redirect@internal\",\"dashboard_stripprefix@internal\"],\"service\":\"dashboard@internal\",\"rule\":\"PathPrefix(`/`)\",\"priority\":2147483645}},\"services\":{\"api\":{},\"dashboard\":{},\"noop\":{}},\"middlewares\":{\"dashboard_redirect\":{\"redirectRegex\":{\"regex\":\"^(http:\\\\/\\\\/(\\\\[[\\\\w:.]+\\\\]|[\\\\w\\\\._-]+)(:\\\\d+)?)\\\\/$\",\"replacement\":\"${1}/dashboard/\",\"permanent\":true}},\"dashboard_stripprefix\":{\"stripPrefix\":{\"prefixes\":[\"/dashboard/\",\"/dashboard\"]}}},\"serversTransports\":{\"default\":{\"maxIdleConnsPerHost\":200}}},\"tcp\":{},\"udp\":{},\"tls\":{}}","providerName":"internal","time":"2023-05-11T14:49:37Z"}
{"level":"info","msg":"Starting provider *docker.Provider","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"*docker.Provider provider configuration: {\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"network\":\"web\",\"swarmModeRefreshSeconds\":\"15s\"}","time":"2023-05-11T14:49:37Z"}
{"level":"info","msg":"Starting provider *acme.ChallengeTLSALPN","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"*acme.ChallengeTLSALPN provider configuration: {}","time":"2023-05-11T14:49:37Z"}
{"level":"info","msg":"Starting provider *acme.Provider","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"*acme.Provider provider configuration: {\"email\":\"exampleapp@gmail.com\",\"caServer\":\"https://acme-v02.api.letsencrypt.org/directory\",\"storage\":\"/etc/ssl/certs/acme.json\",\"keyType\":\"RSA4096\",\"certificatesDuration\":2160,\"tlsChallenge\":{},\"ResolverName\":\"le\",\"store\":{},\"TLSChallengeProvider\":{},\"HTTPChallengeProvider\":{}}","time":"2023-05-11T14:49:37Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Attempt to renew certificates \"720h0m0s\" before expiry and check every \"24h0m0s\"","providerName":"le.acme","time":"2023-05-11T14:49:37Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"info","msg":"Testing certificate renew...","providerName":"le.acme","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"Configuration received: {\"http\":{},\"tcp\":{},\"udp\":{},\"tls\":{}}","providerName":"le.acme","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"Provider connection established with docker 20.10.21 (API 1.41)","providerName":"docker","time":"2023-05-11T14:49:37Z"}
{"container":"traefik-server-d70500d56b426990754461f75c0b97c54857bdfbc49344658048d765e868df36","level":"debug","msg":"Could not find network named \"web\" for container \"/server_traefik_1\". Maybe you're missing the project's prefix in the label?","providerName":"docker","serviceName":"traefik-server","time":"2023-05-11T14:49:37Z"}
{"container":"traefik-server-d70500d56b426990754461f75c0b97c54857bdfbc49344658048d765e868df36","level":"error","msg":"service \"traefik-server\" error: port is missing","providerName":"docker","time":"2023-05-11T14:49:37Z"}
{"container":"db-server-f993158dac7c9da7c2a21ee8cb7638a885d527bc368b76a6b0214b223ce37e45","level":"debug","msg":"Filtering disabled container","providerName":"docker","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"Configuration received: {\"http\":{\"routers\":{\"api\":{\"entryPoints\":[\"websecure\"],\"service\":\"api\",\"rule\":\"Host(`test-api.exampleapp.de`) \\u0026\\u0026 PathPrefix(`/api`)\",\"tls\":{\"certResolver\":\"le\"}},\"pgadmin\":{\"entryPoints\":[\"websecure\"],\"service\":\"pgadmin\",\"rule\":\"Host(`test-api.exampleapp.de`) \\u0026\\u0026 PathPrefix(`/pgadmin`)\",\"tls\":{\"certResolver\":\"le\"}}},\"services\":{\"api\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.18.0.2:3000\"}],\"passHostHeader\":true}},\"pgadmin\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.18.0.3:80\"}],\"passHostHeader\":true}}}},\"tcp\":{},\"udp\":{}}","providerName":"docker","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"No default certificate, fallback to the internal generated certificate","time":"2023-05-11T14:49:37Z","tlsStoreName":"default"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware dashboard@internal","routerName":"dashboard@internal","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","middlewareType":"StripPrefix","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Setting up redirection from ^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$ to ${1}/dashboard/","routerName":"dashboard@internal","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware api@internal","routerName":"api@internal","time":"2023-05-11T14:49:37Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"traefik-internal-recovery","middlewareType":"Recovery","msg":"Creating middleware","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"Adding certificate for domain(s) test-api.exampleapp.de","time":"2023-05-11T14:49:37Z"}
{"level":"debug","msg":"No default certificate, fallback to the internal generated certificate","time":"2023-05-11T14:49:38Z","tlsStoreName":"default"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware api@internal","routerName":"api@internal","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware dashboard@internal","routerName":"dashboard@internal","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","middlewareType":"StripPrefix","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Setting up redirection from ^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$ to ${1}/dashboard/","routerName":"dashboard@internal","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"traefik-internal-recovery","middlewareType":"Recovery","msg":"Creating middleware","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"pipelining","middlewareType":"Pipelining","msg":"Creating middleware","routerName":"api@docker","serviceName":"api","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating load-balancer","routerName":"api@docker","serviceName":"api","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating server 0 http://172.18.0.2:3000","routerName":"api@docker","serverName":0,"serviceName":"api","time":"2023-05-11T14:49:38Z"}
{"level":"debug","msg":"child http://172.18.0.2:3000 now UP","time":"2023-05-11T14:49:38Z"}
{"level":"debug","msg":"Propagating new UP status","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware api","routerName":"api@docker","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"pipelining","middlewareType":"Pipelining","msg":"Creating middleware","routerName":"pgadmin@docker","serviceName":"pgadmin","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating load-balancer","routerName":"pgadmin@docker","serviceName":"pgadmin","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating server 0 http://172.18.0.3:80","routerName":"pgadmin@docker","serverName":0,"serviceName":"pgadmin","time":"2023-05-11T14:49:38Z"}
{"level":"debug","msg":"child http://172.18.0.3:80 now UP","time":"2023-05-11T14:49:38Z"}
{"level":"debug","msg":"Propagating new UP status","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware pgadmin","routerName":"pgadmin@docker","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"traefik-internal-recovery","middlewareType":"Recovery","msg":"Creating middleware","time":"2023-05-11T14:49:38Z"}
{"entryPointName":"websecure","level":"debug","msg":"Adding route for test-api.exampleapp.de with TLS options default","time":"2023-05-11T14:49:38Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.exampleapp.de] found in HostSNI rule","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.exampleapp.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-11T14:49:38Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.exampleapp.de] found in HostSNI rule","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.exampleapp.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-11T14:49:38Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.exampleapp.de\"]...","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.exampleapp.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-11T14:49:38Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.exampleapp.de\"].","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.exampleapp.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-11T14:49:38Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.exampleapp.de\"]...","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.exampleapp.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-11T14:49:38Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.exampleapp.de\"].","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.exampleapp.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-11T14:49:38Z"}

Make sure to use traefik (not api) in all routers on Traefik, so it doesn't conflict with your service

1 Like

You tell Traefik to use the network, but the container itself is not connected to it.

Don't use host mode, but only expose used ports for Traefik (80, 443, maybe 8080).

1 Like

Thank you. The 404 Error is now gone, but I'm getting a "Gateway Timeout" on /api and /pgadmin.

docker-compose:

version: '3.5'
services:
  traefik:
    image: traefik:v2.10.1
    restart: always
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=web
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --api.insecure=true
      - --certificatesresolvers.le.acme.email=${LETSENCRYPT_MAIL}
      - --certificatesresolvers.le.acme.storage=/etc/ssl/certs/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
      - --log.level=DEBUG
      - --log.filePath=/etc/traefik/traefik.log
      - --log.format=json
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.traefik.rule=Host(`${DOMAIN_NAME}`)
      - traefik.http.routers.traefik.tls.certresolver=le
      - traefik.http.routers.traefik.entrypoints=websecure
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/ssl/certs:/etc/ssl/certs
      - /etc/traefik:/etc/traefik

  detactive_api:
    build: api
    restart: always
    environment:
      - DETACTIVE_DB_URL=${DETACTIVE_DB_URL}
      - STICKER_DB_URL=${STICKER_DB_URL}
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.api.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/api`)
      - traefik.http.services.api.loadbalancer.server.port=3000
      - traefik.http.routers.api.tls.certresolver=le
      - traefik.http.routers.api.entrypoints=websecure
    depends_on:
      - db
    networks:
      - web
      - internal

  db:
    image: postgres
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - ./api/db/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - internal

  pgadmin:
    image: dpage/pgadmin4
    restart: always
    environment:
      - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL}
      - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD}
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.pgadmin.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/pgadmin`)
      - traefik.http.services.pgadmin.loadbalancer.server.port=80
      - traefik.http.routers.pgadmin.tls.certresolver=le
      - traefik.http.routers.pgadmin.entrypoints=websecure
    networks:
      - web
      - internal

networks:
  web:
    external: true
  internal:
    external: false

logs:

{"entryPointName":"websecure","level":"debug","msg":"Adding route for test-api.hostname.de with TLS options default","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.hostname.de] found in HostSNI rule","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.hostname.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.hostname.de] found in HostSNI rule","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.hostname.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.hostname.de] found in HostSNI rule","providerName":"le.acme","routerName":"traefik@docker","rule":"Host(`test-api.hostname.de`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.hostname.de\"]...","providerName":"le.acme","routerName":"traefik@docker","rule":"Host(`test-api.hostname.de`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.hostname.de\"].","providerName":"le.acme","routerName":"traefik@docker","rule":"Host(`test-api.hostname.de`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.hostname.de\"]...","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.hostname.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.hostname.de\"].","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.hostname.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.hostname.de\"]...","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.hostname.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-12T15:29:56Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.hostname.de\"].","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.hostname.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-12T15:29:56Z"}
{"level":"debug","msg":"'504 Gateway Timeout' caused by: dial tcp 172.18.0.2:3000: i/o timeout","time":"2023-05-12T15:30:38Z"}
{"level":"debug","msg":"'504 Gateway Timeout' caused by: dial tcp 172.18.0.2:3000: i/o timeout","time":"2023-05-12T15:31:41Z"}
{"level":"debug","msg":"Serving default certificate for request: \"\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"82.165.76.150\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59710: EOF","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"82.165.76.150\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59726: EOF","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"82.165.76.150\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59734: tls: no cipher suite supported by both client and server","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59736: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59742: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59758: tls: client offered only unsupported versions: [302 301]","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"82.165.76.150\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59772: EOF","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"82.165.76.150\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59784: EOF","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"82.165.76.150\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59796: EOF","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"82.165.76.150\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"http: TLS handshake error from 51.158.241.133:59802: EOF","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"Serving default certificate for request: \"\"","time":"2023-05-12T15:32:12Z"}
{"level":"debug","msg":"'504 Gateway Timeout' caused by: dial tcp 172.18.0.2:3000: i/o timeout","time":"2023-05-12T15:32:52Z"}
{"level":"debug","msg":"'504 Gateway Timeout' caused by: dial tcp 172.18.0.3:80: i/o timeout","time":"2023-05-12T15:33:14Z"}
{"level":"debug","msg":"'499 Client Closed Request' caused by: context canceled","time":"2023-05-12T15:34:08Z"}
{"level":"debug","msg":"'499 Client Closed Request' caused by: context canceled","time":"2023-05-12T15:34:17Z"}
{"level":"debug","msg":"'499 Client Closed Request' caused by: context canceled","time":"2023-05-12T15:34:41Z"}
{"level":"debug","msg":"'499 Client Closed Request' caused by: context canceled","time":"2023-05-12T15:35:03Z"}
{"level":"debug","msg":"'504 Gateway Timeout' caused by: dial tcp 172.18.0.2:3000: i/o timeout","time":"2023-05-12T15:35:33Z"}

Traefik is missing network: -web.

1 Like

My bad... Now I'm getting the 404 again. :no_mouth:

docker-compose.yml:

version: '3.5'
services:
  traefik:
    image: traefik:v2.10.1
    restart: always
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=web
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --api.insecure=true
      - --certificatesresolvers.le.acme.email=${LETSENCRYPT_MAIL}
      - --certificatesresolvers.le.acme.storage=/etc/ssl/certs/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
      - --log.level=DEBUG
      - --log.filePath=/etc/traefik/traefik.log
      - --log.format=json
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.traefik.rule=Host(`${DOMAIN_NAME}`)
      - traefik.http.routers.traefik.tls.certresolver=le
      - traefik.http.routers.traefik.entrypoints=websecure
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/ssl/certs:/etc/ssl/certs
      - /etc/traefik:/etc/traefik
    networks:
      - web

  detactive_api:
    build: api
    restart: always
    environment:
      - DETACTIVE_DB_URL=${DETACTIVE_DB_URL}
      - STICKER_DB_URL=${STICKER_DB_URL}
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.api.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/api`)
      - traefik.http.services.api.loadbalancer.server.port=3000
      - traefik.http.routers.api.tls.certresolver=le
      - traefik.http.routers.api.entrypoints=websecure
    depends_on:
      - db
    networks:
      - web

  db:
    image: postgres
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - ./api/db/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - internal

  pgadmin:
    image: dpage/pgadmin4
    restart: always
    environment:
      - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL}
      - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD}
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.pgadmin.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/pgadmin`)
      - traefik.http.services.pgadmin.loadbalancer.server.port=80
      - traefik.http.routers.pgadmin.tls.certresolver=le
      - traefik.http.routers.pgadmin.entrypoints=websecure
    networks:
      - web
      - internal

networks:
  web:
    external: true
  internal:
    external: false

Logs:


{"entryPointName":"websecure","level":"debug","msg":"Waiting 10s seconds before killing connections.","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"traefik","level":"debug","msg":"Waiting 10s seconds before killing connections.","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"websecure","level":"error","msg":"accept tcp [::]:443: use of closed network connection","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"websecure","level":"error","msg":"Error while starting server: accept tcp [::]:443: use of closed network connection","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"traefik","level":"error","msg":"accept tcp [::]:8080: use of closed network connection","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"traefik","level":"error","msg":"Error while starting server: accept tcp [::]:8080: use of closed network connection","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"traefik","level":"debug","msg":"Entry point traefik closed","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"web","level":"debug","msg":"Waiting 10s seconds before killing connections.","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"websecure","level":"debug","msg":"Entry point websecure closed","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"web","level":"error","msg":"accept tcp [::]:80: use of closed network connection","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"web","level":"error","msg":"Error while starting server: accept tcp [::]:80: use of closed network connection","time":"2023-05-12T17:57:36Z"}
{"entryPointName":"web","level":"debug","msg":"Entry point web closed","time":"2023-05-12T17:57:36Z"}
{"level":"info","msg":"Server stopped","time":"2023-05-12T17:57:36Z"}
{"level":"info","msg":"Shutting down","time":"2023-05-12T17:57:36Z"}
{"level":"info","msg":"Traefik version 2.10.1 built on 2023-04-27T14:52:35Z","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Static configuration loaded {\"global\":{\"checkNewVersion\":true},\"serversTransport\":{\"maxIdleConnsPerHost\":200},\"entryPoints\":{\"traefik\":{\"address\":\":8080\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":\"10s\"},\"respondingTimeouts\":{\"idleTimeout\":\"3m0s\"}},\"forwardedHeaders\":{},\"http\":{},\"http2\":{\"maxConcurrentStreams\":250},\"udp\":{\"timeout\":\"3s\"}},\"web\":{\"address\":\":80\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":\"10s\"},\"respondingTimeouts\":{\"idleTimeout\":\"3m0s\"}},\"forwardedHeaders\":{},\"http\":{},\"http2\":{\"maxConcurrentStreams\":250},\"udp\":{\"timeout\":\"3s\"}},\"websecure\":{\"address\":\":443\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":\"10s\"},\"respondingTimeouts\":{\"idleTimeout\":\"3m0s\"}},\"forwardedHeaders\":{},\"http\":{},\"http2\":{\"maxConcurrentStreams\":250},\"udp\":{\"timeout\":\"3s\"}}},\"providers\":{\"providersThrottleDuration\":\"2s\",\"docker\":{\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"network\":\"web\",\"swarmModeRefreshSeconds\":\"15s\"}},\"api\":{\"insecure\":true,\"dashboard\":true},\"log\":{\"level\":\"DEBUG\",\"filePath\":\"/etc/traefik/traefik.log\",\"format\":\"json\"},\"certificatesResolvers\":{\"le\":{\"acme\":{\"email\":\"testapp.app@gmail.com\",\"caServer\":\"https://acme-v02.api.letsencrypt.org/directory\",\"storage\":\"/etc/ssl/certs/acme.json\",\"keyType\":\"RSA4096\",\"certificatesDuration\":2160,\"tlsChallenge\":{}}}}}","time":"2023-05-12T17:57:39Z"}
{"level":"info","msg":"\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://doc.traefik.io/traefik/contributing/data-collection/\n","time":"2023-05-12T17:57:39Z"}
{"level":"info","msg":"Starting provider aggregator aggregator.ProviderAggregator","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","msg":"Starting TCP Server","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"web","level":"debug","msg":"Starting TCP Server","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Starting TCP Server","time":"2023-05-12T17:57:39Z"}
{"level":"info","msg":"Starting provider *traefik.Provider","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"*traefik.Provider provider configuration: {}","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Configuration received: {\"http\":{\"routers\":{\"api\":{\"entryPoints\":[\"traefik\"],\"service\":\"api@internal\",\"rule\":\"PathPrefix(`/api`)\",\"priority\":2147483646},\"dashboard\":{\"entryPoints\":[\"traefik\"],\"middlewares\":[\"dashboard_redirect@internal\",\"dashboard_stripprefix@internal\"],\"service\":\"dashboard@internal\",\"rule\":\"PathPrefix(`/`)\",\"priority\":2147483645}},\"services\":{\"api\":{},\"dashboard\":{},\"noop\":{}},\"middlewares\":{\"dashboard_redirect\":{\"redirectRegex\":{\"regex\":\"^(http:\\\\/\\\\/(\\\\[[\\\\w:.]+\\\\]|[\\\\w\\\\._-]+)(:\\\\d+)?)\\\\/$\",\"replacement\":\"${1}/dashboard/\",\"permanent\":true}},\"dashboard_stripprefix\":{\"stripPrefix\":{\"prefixes\":[\"/dashboard/\",\"/dashboard\"]}}},\"serversTransports\":{\"default\":{\"maxIdleConnsPerHost\":200}}},\"tcp\":{},\"udp\":{},\"tls\":{}}","providerName":"internal","time":"2023-05-12T17:57:39Z"}
{"level":"info","msg":"Starting provider *docker.Provider","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"*docker.Provider provider configuration: {\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"network\":\"web\",\"swarmModeRefreshSeconds\":\"15s\"}","time":"2023-05-12T17:57:39Z"}
{"level":"info","msg":"Starting provider *acme.ChallengeTLSALPN","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"*acme.ChallengeTLSALPN provider configuration: {}","time":"2023-05-12T17:57:39Z"}
{"level":"info","msg":"Starting provider *acme.Provider","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"*acme.Provider provider configuration: {\"email\":\"testapp.app@gmail.com\",\"caServer\":\"https://acme-v02.api.letsencrypt.org/directory\",\"storage\":\"/etc/ssl/certs/acme.json\",\"keyType\":\"RSA4096\",\"certificatesDuration\":2160,\"tlsChallenge\":{},\"ResolverName\":\"le\",\"store\":{},\"TLSChallengeProvider\":{},\"HTTPChallengeProvider\":{}}","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Attempt to renew certificates \"720h0m0s\" before expiry and check every \"24h0m0s\"","providerName":"le.acme","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"info","msg":"Testing certificate renew...","providerName":"le.acme","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Configuration received: {\"http\":{},\"tcp\":{},\"udp\":{},\"tls\":{}}","providerName":"le.acme","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Provider connection established with docker 20.10.21 (API 1.41)","providerName":"docker","time":"2023-05-12T17:57:39Z"}
{"container":"db-server-73b19d3ead292ed1594355d6f0d5281031b0b8c0cd26de4ac98ac42d0586b4ee","level":"debug","msg":"Filtering disabled container","providerName":"docker","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Configuration received: {\"http\":{\"routers\":{\"api\":{\"entryPoints\":[\"websecure\"],\"service\":\"api\",\"rule\":\"Host(`test-api.testapp.de`) \\u0026\\u0026 PathPrefix(`/api`)\",\"tls\":{\"certResolver\":\"le\"}},\"pgadmin\":{\"entryPoints\":[\"websecure\"],\"service\":\"pgadmin\",\"rule\":\"Host(`test-api.testapp.de`) \\u0026\\u0026 PathPrefix(`/pgadmin`)\",\"tls\":{\"certResolver\":\"le\"}},\"traefik\":{\"entryPoints\":[\"websecure\"],\"service\":\"traefik-server\",\"rule\":\"Host(`test-api.testapp.de`)\",\"tls\":{\"certResolver\":\"le\"}}},\"services\":{\"api\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.18.0.2:3000\"}],\"passHostHeader\":true}},\"pgadmin\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.18.0.3:80\"}],\"passHostHeader\":true}},\"traefik-server\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.18.0.4:80\"}],\"passHostHeader\":true}}}},\"tcp\":{},\"udp\":{}}","providerName":"docker","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"No default certificate, fallback to the internal generated certificate","time":"2023-05-12T17:57:39Z","tlsStoreName":"default"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware dashboard@internal","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","middlewareType":"StripPrefix","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Setting up redirection from ^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$ to ${1}/dashboard/","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware api@internal","routerName":"api@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"traefik-internal-recovery","middlewareType":"Recovery","msg":"Creating middleware","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Adding certificate for domain(s) test-api.testapp.de","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"No default certificate, fallback to the internal generated certificate","time":"2023-05-12T17:57:39Z","tlsStoreName":"default"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware api@internal","routerName":"api@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware dashboard@internal","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","middlewareType":"StripPrefix","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_stripprefix@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Creating middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","middlewareType":"RedirectRegex","msg":"Setting up redirection from ^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$ to ${1}/dashboard/","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"dashboard_redirect@internal","msg":"Adding tracing to middleware","routerName":"dashboard@internal","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"traefik","level":"debug","middlewareName":"traefik-internal-recovery","middlewareType":"Recovery","msg":"Creating middleware","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"pipelining","middlewareType":"Pipelining","msg":"Creating middleware","routerName":"pgadmin@docker","serviceName":"pgadmin","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating load-balancer","routerName":"pgadmin@docker","serviceName":"pgadmin","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating server 0 http://172.18.0.3:80","routerName":"pgadmin@docker","serverName":0,"serviceName":"pgadmin","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"child http://172.18.0.3:80 now UP","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Propagating new UP status","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware pgadmin","routerName":"pgadmin@docker","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"pipelining","middlewareType":"Pipelining","msg":"Creating middleware","routerName":"traefik@docker","serviceName":"traefik-server","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating load-balancer","routerName":"traefik@docker","serviceName":"traefik-server","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating server 0 http://172.18.0.4:80","routerName":"traefik@docker","serverName":0,"serviceName":"traefik-server","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"child http://172.18.0.4:80 now UP","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Propagating new UP status","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware traefik-server","routerName":"traefik@docker","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"pipelining","middlewareType":"Pipelining","msg":"Creating middleware","routerName":"api@docker","serviceName":"api","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating load-balancer","routerName":"api@docker","serviceName":"api","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Creating server 0 http://172.18.0.2:3000","routerName":"api@docker","serverName":0,"serviceName":"api","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"child http://172.18.0.2:3000 now UP","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Propagating new UP status","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"tracing","middlewareType":"TracingForwarder","msg":"Added outgoing tracing middleware api","routerName":"api@docker","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","middlewareName":"traefik-internal-recovery","middlewareType":"Recovery","msg":"Creating middleware","time":"2023-05-12T17:57:39Z"}
{"entryPointName":"websecure","level":"debug","msg":"Adding route for test-api.testapp.de with TLS options default","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.testapp.de] found in HostSNI rule","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.testapp.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.testapp.de] found in HostSNI rule","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.testapp.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Trying to challenge certificate for domain [test-api.testapp.de] found in HostSNI rule","providerName":"le.acme","routerName":"traefik@docker","rule":"Host(`test-api.testapp.de`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.testapp.de\"]...","providerName":"le.acme","routerName":"traefik@docker","rule":"Host(`test-api.testapp.de`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.testapp.de\"].","providerName":"le.acme","routerName":"traefik@docker","rule":"Host(`test-api.testapp.de`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.testapp.de\"]...","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.testapp.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.testapp.de\"].","providerName":"le.acme","routerName":"api@docker","rule":"Host(`test-api.testapp.de`) \u0026\u0026 PathPrefix(`/api`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"Looking for provided certificate(s) to validate [\"test-api.testapp.de\"]...","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.testapp.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-12T17:57:39Z"}
{"ACME CA":"https://acme-v02.api.letsencrypt.org/directory","level":"debug","msg":"No ACME certificate generation required for domains [\"test-api.testapp.de\"].","providerName":"le.acme","routerName":"pgadmin@docker","rule":"Host(`test-api.testapp.de`) \u0026\u0026 PathPrefix(`/pgadmin`)","time":"2023-05-12T17:57:39Z"}
{"level":"debug","msg":"Serving default certificate for request: \"\"","time":"2023-05-12T17:58:16Z"}

Did you use host + path?

Enable Traefik dashboard and check it.

1 Like

Yup. That should be right...

https://host/api should show your api.

This does nothing:

labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.traefik.rule=Host(`${DOMAIN_NAME}`)
      - traefik.http.routers.traefik.tls.certresolver=le
      - traefik.http.routers.traefik.entrypoints=websecure

No service assigned and dashboard in insecure mode will automatically listen on http://host:8080/dashboard/.

1 Like

Finally I got /pgadmin working by setting the SCRIPT_NAME env var.
See here: Container Deployment — pgAdmin 4 7.1 documentation

But /api still gives me 404.

docker-compose.yml:

version: '3.5'
services:
  traefik:
    image: traefik:v2.10.1
    restart: always
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=web
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --api.insecure=true
      - --certificatesresolvers.le.acme.email=${LETSENCRYPT_MAIL}
      - --certificatesresolvers.le.acme.storage=/etc/ssl/certs/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
      - --log.level=DEBUG
      - --log.filePath=/etc/traefik/traefik.log
      - --log.format=json
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/ssl/certs:/etc/ssl/certs
      - /etc/traefik:/etc/traefik
    networks:
      - web

  detactive_api:
    build: api
    restart: always
    env_file: .env
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.api.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/api`)
      - traefik.http.services.api.loadbalancer.server.port=3000
      - traefik.http.routers.api.tls.certresolver=le
      - traefik.http.routers.api.entrypoints=websecure
    depends_on:
      - db
    networks:
      - web

  db:
    image: postgres
    restart: always
    env_file: .env
    volumes:
      - ./api/db/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - web

  pgadmin:
    image: dpage/pgadmin4
    restart: always
    env_file: .env
    environment:
      - SCRIPT_NAME=/pgadmin
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
      - traefik.http.routers.pgadmin.rule=Host(`${DOMAIN_NAME}`) && PathPrefix(`/pgadmin`)
      - traefik.http.services.pgadmin.loadbalancer.server.port=80
      - traefik.http.routers.pgadmin.tls.certresolver=le
      - traefik.http.routers.pgadmin.entrypoints=websecure
    networks:
      - web

networks:
  web:
    external: true
  internal:
    external: false

Is db running?

api depends on db, but personally I would let api handle "no db" more gracefully than not be started by Docker.

What URL do you call to test api?

1 Like

All services are running.

The /api url is: https://test-api.detactive.de/api

root@localhost:~# curl localhost:3000
Detactive API v1.0.0root@localhost:~# docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED                                                                                                                                                                          STATUS             PORTS                                                                                                                                                                                                                                   NAMES
8c412857e771   server_detactive_api   "./detactive-api"        28 seconds ago                                                                                                                                                                   Up 26 seconds      0.0.0.0:3000->3000/tcp, :::3000->3000/tcp                                                                                                                                                                                               server_detactive_api_1
d8d9e7b07e9b   traefik:v2.10.1        "/entrypoint.sh --pr…"   6 minutes ago                                                                                                                                                                    Up 6 minutes       0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :                                                                                                                                                             ::443->443/tcp   server_traefik_1
b664f28f395e   postgres               "docker-entrypoint.s…"   29 minutes ago                                                                                                                                                                   Up 29 minutes      0.0.0.0:5432->5432/tcp, :::5432->5432/tcp                                                                                                                                                                                               server_db_1
3b52cbaa420b   dpage/pgadmin4         "/entrypoint.sh"         About an hour ago                                                                                                                                                                Up About an hour   80/tcp, 443/tcp                                                                                                                                                                                                                         server_pgadmin_1

Do you have a file /etc/traefik/traefik.yml? That would override your command settings. Docs.

1 Like

Nope, there is no config file for Traefik.

root@localhost:/etc/traefik# ls
traefik.log