From cf53242dcaf99f3fd4030ab1e956db7b61986579 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Mon, 24 Feb 2025 14:58:59 +0100 Subject: [PATCH] First work on infra with traefik --- infra/.dockerignore | 5 ++ infra/Dockerfile | 11 ++++ infra/app/main.py | 7 +++ infra/docker-compose.override.yaml | 8 +++ infra/docker-compose.traefik.yaml | 80 ++++++++++++++++++++++++++++++ infra/docker-compose.yaml | 50 ++++++++++++------- infra/requirements.txt | 2 + 7 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 infra/.dockerignore create mode 100644 infra/Dockerfile create mode 100644 infra/app/main.py create mode 100644 infra/docker-compose.override.yaml create mode 100644 infra/docker-compose.traefik.yaml create mode 100644 infra/requirements.txt diff --git a/infra/.dockerignore b/infra/.dockerignore new file mode 100644 index 0000000..c435315 --- /dev/null +++ b/infra/.dockerignore @@ -0,0 +1,5 @@ +.env3.8 +.mypy_cache +__pycache__ +*.pyc +.vscode \ No newline at end of file diff --git a/infra/Dockerfile b/infra/Dockerfile new file mode 100644 index 0000000..8f9ade9 --- /dev/null +++ b/infra/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--workers", "4"] \ No newline at end of file diff --git a/infra/app/main.py b/infra/app/main.py new file mode 100644 index 0000000..a4af609 --- /dev/null +++ b/infra/app/main.py @@ -0,0 +1,7 @@ +from fastapi import FastAPI + +app = FastAPI() + +@app.get("/") +def read_main(): + return {"message": "hello world from traefik"} \ No newline at end of file diff --git a/infra/docker-compose.override.yaml b/infra/docker-compose.override.yaml new file mode 100644 index 0000000..bfb068b --- /dev/null +++ b/infra/docker-compose.override.yaml @@ -0,0 +1,8 @@ +services: + backend: + ports: + - 80:80 + +networks: + traefik-public: + external: false diff --git a/infra/docker-compose.traefik.yaml b/infra/docker-compose.traefik.yaml new file mode 100644 index 0000000..8daba39 --- /dev/null +++ b/infra/docker-compose.traefik.yaml @@ -0,0 +1,80 @@ +services: + traefik: + # Use the latest v2.3.x Traefik image available + image: traefik:v2.3 + ports: + # Listen on port 80, default for HTTP, necessary to redirect to HTTPS + - 80:80 + # Listen on port 443, default for HTTPS + - 443:443 + restart: always + labels: + # Enable Traefik for this service, to make it available in the public network + - traefik.enable=true + # Define the port inside of the Docker service to use + - traefik.http.services.traefik-dashboard.loadbalancer.server.port=8080 + # Make Traefik use this domain in HTTP + - traefik.http.routers.traefik-dashboard-http.entrypoints=http + - traefik.http.routers.traefik-dashboard-http.rule=Host(`api.xtablo.com`) + # Use the traefik-public network (declared below) + - traefik.docker.network=traefik-public + # traefik-https the actual router using HTTPS + - traefik.http.routers.traefik-dashboard-https.entrypoints=https + - traefik.http.routers.traefik-dashboard-https.rule=Host(`api.xtablo.com`) + - traefik.http.routers.traefik-dashboard-https.tls=true + # Use the "le" (Let's Encrypt) resolver created below + - traefik.http.routers.traefik-dashboard-https.tls.certresolver=le + # Use the special Traefik service api@internal with the web UI/Dashboard + - traefik.http.routers.traefik-dashboard-https.service=api@internal + # https-redirect middleware to redirect HTTP to HTTPS + - traefik.http.middlewares.https-redirect.redirectscheme.scheme=https + - traefik.http.middlewares.https-redirect.redirectscheme.permanent=true + # traefik-http set up only to use the middleware to redirect to https + - traefik.http.routers.traefik-dashboard-http.middlewares=https-redirect + # admin-auth middleware with HTTP Basic auth + # Using the environment variables USERNAME and HASHED_PASSWORD + - traefik.http.middlewares.admin-auth.basicauth.users=${USERNAME?Variable not set}:${HASHED_PASSWORD?Variable not set} + # Enable HTTP Basic auth, using the middleware created above + - traefik.http.routers.traefik-dashboard-https.middlewares=admin-auth + volumes: + # Add Docker as a mounted volume, so that Traefik can read the labels of other services + - /var/run/docker.sock:/var/run/docker.sock:ro + # Mount the volume to store the certificates + - /home/arthur/acme.json:/acme.json + command: + # Enable Docker in Traefik, so that it reads labels from Docker services + - --providers.docker + # Do not expose all Docker services, only the ones explicitly exposed + - --providers.docker.exposedbydefault=false + # Create an entrypoint "http" listening on port 80 + - --entrypoints.http.address=:80 + # Create an entrypoint "https" listening on port 443 + - --entrypoints.https.address=:443 + # Create the certificate resolver "le" for Let's Encrypt, uses the environment variable EMAIL + - --certificatesresolvers.le.acme.email=arbelleville@gmail.com + # Store the Let's Encrypt certificates in the mounted volume + - --certificatesresolvers.le.acme.storage=/acme.json + # Use the TLS Challenge for Let's Encrypt + - --certificatesresolvers.le.acme.tlschallenge=true + # Enable the access log, with HTTP requests + - --accesslog + # Enable the Traefik log, for configurations and errors + - --log + # Enable the Dashboard and API + - --api + networks: + # Use the public network created to be shared between Traefik and + # any other service that needs to be publicly available with HTTPS + - traefik-public + +volumes: + # Create a volume to store the certificates, there is a constraint to make sure + # Traefik is always deployed to the same Docker node with the same volume containing + # the HTTPS certificates + traefik-public-certificates: + +networks: + # Use the previously created public network "traefik-public", shared with other + # services that need to be publicly available via this Traefik + traefik-public: + external: true diff --git a/infra/docker-compose.yaml b/infra/docker-compose.yaml index 8593de2..66ea8e0 100644 --- a/infra/docker-compose.yaml +++ b/infra/docker-compose.yaml @@ -1,22 +1,34 @@ -name: xtablo +services: + backend: + build: ./ + restart: always + labels: + # Enable Traefik for this specific "backend" service + - traefik.enable=true + # Define the port inside of the Docker service to use + - traefik.http.services.app.loadbalancer.server.port=80 + # Make Traefik use this domain in HTTP + - traefik.http.routers.app-http.entrypoints=http + - traefik.http.routers.app-http.rule=Host(`api.xtablo.com`) + # Use the traefik-public network (declared below) + - traefik.docker.network=traefik-public + # Make Traefik use this domain in HTTPS + - traefik.http.routers.app-https.entrypoints=https + - traefik.http.routers.app-https.rule=Host(`api.xtablo.com`) + - traefik.http.routers.app-https.tls=true + # Use the "le" (Let's Encrypt) resolver + - traefik.http.routers.app-https.tls.certresolver=le + # https-redirect middleware to redirect HTTP to HTTPS + - traefik.http.middlewares.https-redirect.redirectscheme.scheme=https + - traefik.http.middlewares.https-redirect.redirectscheme.permanent=true + # Middleware to redirect HTTP to HTTPS + - traefik.http.routers.app-http.middlewares=https-redirect + - traefik.http.routers.app-https.middlewares=admin-auth + networks: + # Use the public network created to be shared between Traefik and + # any other service that needs to be publicly available with HTTPS + - traefik-public networks: - default: + traefik-public: external: true - name: web - -services: - app: - image: "jc21/nginx-proxy-manager:latest" - restart: unless-stopped - ports: - # these ports are in format : - - "80:80" # public http port - - "443:443" # public https port - - "81:81" # admin web port - expose: - - "81" - volumes: - - ./data:/data - - ./letsencrypt:/etc/letsencrypt - - ./logs:/var/logs/nginx diff --git a/infra/requirements.txt b/infra/requirements.txt new file mode 100644 index 0000000..0ad15ed --- /dev/null +++ b/infra/requirements.txt @@ -0,0 +1,2 @@ +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 \ No newline at end of file