Docker-setup

Zoals toegelicht in het hoofdstuk Draaien in dev omgeving, hebben we Docker op Windows en macOS gebruikt. De Dockerfile- en docker-compose.yml-bestanden hiervoor staan in de betreffende repositories. Deze bestanden kunnen ook helpen om het project in productie te zetten.

Hiervoor is wel aanvullende configuratie nodig. Deze staat reeds ter demo op de server die we van school gekregen hebben, maar lichten we ter archivering en toelichting ook hier uit.

Verwachte bestandsstructuur

Alle Docker-configuratie is gebouwd op relatieve paden. Hierdoor maakt het niet uit waar je de verwachte bestandsstructuur hebt. De structuur zelf is wel belangrijk. Binnen de huidige server staan deze bestanden in de Linux-profielmap: /home/groep2.

[root]/Sources/rott-backend         # Clone van de backend repo.
[root]/Sources/rott-backend/.env    # Backend configuratie, een kopie van de `.env.example` voldoet om te starten.
[root]/Sources/rott-backend/app.log # Log-bestand, maak dit bestand leeg aan VOOR je het project start, bijvoorbeeld met het commando `touch app.log`.
[root]/Sources/rott-frontend        # Clone van de frontend repo.
[root]/Sources/rott-docs            # Clone van de docs repo.
[root]/compose.yml                  # Docker Compose file met HTTP(S) reverse proxy, frontend en docs.
[root]/override.yml                 # Docker Compose file met productie-overrides op de Docker-bestanden uit de repo.

Configuratie

De volgende Docker Compose-file combineert de Docker Compose-file uit de backend repo met configuratie om:

  • Alle services (frontend, backend en docs) beschikbaar te maken via HTTPS middels Traefik.
    • Traefik maakt gebruik van de services van Let's Encrypt om automatisch te voorzien in SSL/TLS-certificaten.
  • Ook Ollama in Docker te draaien.
    • Hoewel dat normaal geen goed idee (GPU-toegang via Docker is ingewikkeld) is, heeft de server vanuit school geen GPU en zou Docker in dit geval geen merkbare vertraging moeten opleveren.
    • In een omgeving waar dit wel verschil zou maken (zie hoofdstuk Hardware), kan de docker-compose-with-ollama.yml file vervangen worden voor docker-compose.yml en dient Ollama direct op de host gedraaid te worden.
  • Het frontend, het backend en de gebruikershandleiding beschikbaar te maken via dezelfde hostname hhs-ai.nl.
  • De overdrachtshandleiding beschikbaar te maken via handover-manual.hhs-ai.nl.

compose.yml

Info

In onderstaand bestand zijn enkele regels uitgecomment met een #. Deze regels dienen ter debug en kunnen in de praktijk het beste gecomment blijven, tenzij er problemen zijn en het noodzakelijk is meer debuginformatie te verzamelen.

include:
  - path:
      - Sources/rott-backend/docker-compose-with-ollama.yml
      - override.yaml

services:
  traefik:
    image: traefik:3.3
    container_name: traefik
    command:
#      - --log.level=DEBUG
      - --api=true
      - --api.dashboard=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false

      # HTTP
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entryPoint.to=websecure
      - --entrypoints.web.http.redirections.entryPoint.scheme=https

      # HTTPS
      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.asDefault
      - --entrypoints.websecure.http3
      - --entrypoints.websecure.http.tls.certresolver=myresolver

      # Let's Encrypt
      - --certificatesresolvers.myresolver.acme.tlschallenge=true
#      - --certificatesresolvers.myresolver-dev.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.myresolver.acme.email=S.A.intHout@student.hhs.nl
      - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
    ports:
      - 80:80
      - 443:443
      - 443:443/udp
    volumes:
      - /run/docker.sock:/var/run/docker.sock:ro
      - traefik-letsencrypt:/letsencrypt
#    labels:
#      - traefik.enable=true
#      - traefik.http.routers.dashboard.rule=Host(`traefik-debug.hhs-ai.nl`)
#      - traefik.http.routers.dashboard.service=api@internal
    networks:
      - backend
    restart: always

  frontend:
    container_name: h-ai-frontend
    build:
      context: ./Sources/rott-frontend
      dockerfile: ./Dockerfile
      args:
        - REACT_APP_API_BASE_URL=https://hhs-ai.nl
    volumes:
      - ./Sources/rott-docs/User/Gebruikershandleiding.pdf:/usr/share/nginx/html/H-AI-Gebruikershandleiding.pdf
    expose:
      - 80
    networks:
      - backend
    labels:
      - traefik.enable=true
      - traefik.http.routers.frontend.rule=Host(`hhs-ai.nl`) && !PathPrefix(`/quizzes`) && !PathPrefix(`/docs`) && !Path(`/openapi.json`)
    restart: always

  docs:
    container_name: h-ai-handover-manual
    build:
      context: ./Sources/rott-docs/Handover
      dockerfile: ./Dockerfile
    expose:
      - 8001
    volumes:
      - ./Sources/rott-docs/Handover:/book-src
    networks:
      - backend
    labels:
      - traefik.enable=true
      - traefik.http.routers.docs.rule=Host(`handover-manual.hhs-ai.nl`)
      - traefik.http.services.docs.loadbalancer.server.port=8001
    restart: always

volumes:
  traefik-letsencrypt:
    name: traefik-letsencrypt

override.yml

services:

  backend:
    expose:
      - 8000
    ports: !override []
    labels:
      - traefik.enable=true
      - traefik.http.routers.backend.rule=Host(`hhs-ai.nl`) && (PathPrefix(`/quizzes`) || PathPrefix(`/docs`) || Path(`/openapi.json`))
      - traefik.http.services.backend.loadbalancer.server.port=8000