Docker & Docker Compose¶
Image publiée vs build local¶
Deux façons d'obtenir l'image :
- Image publiée :
cyrius44/wireguard-ui:latest(multi-archlinux/amd64/linux/arm64) — voir Démarrage rapide. - Build local :
docker-compose.yamlà la racine du dépôt construit l'image depuis leDockerfilelocal.
Dockerfile — build multi-stage¶
Stage 1 — build du frontend Angular¶
FROM node:22-alpine AS frontend-builder
WORKDIR /build/frontend
COPY frontend/package.json ./
RUN npm install
COPY frontend/ ./
RUN npm run build
Sortie : frontend/dist/wireguard-ui/browser.
Stage 2 — image finale (backend + assets)¶
FROM python:3.14-alpine
RUN apk add --no-cache curl wireguard-tools iptables supervisor ca-certificates
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
COPY ./docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
WORKDIR /app
RUN --mount=type=bind,source=backend/pyproject.toml,target=pyproject.toml \
--mount=type=bind,source=backend/uv.lock,target=uv.lock \
uv sync --frozen --no-dev
COPY --from=frontend-builder /build/frontend/dist/wireguard-ui/browser ./frontend
COPY backend ./backend
HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \
CMD curl -f http://localhost:8000/api/health || exit 1
VOLUME [ "/etc/wireguard", "/var/lib/wireguard-ui" ]
EXPOSE 8000/tcp 51820/udp
CMD ["/entrypoint.sh"]
Points clés :
wireguard-tools,iptables: nécessaires pour quewg/wg-quicket les règles NAT fonctionnent dans le conteneur.uv sync --frozen --no-dev: installe exactement les dépendances verrouillées dansuv.lock, sans les outils de dev (ruff,mypy…).- Le build Angular (
./frontend) et le code backend (./backend) sont copiés côte à côte sous/app, ce qui correspond à la disposition attendue parmain.py(serve_sparemonte àparents[2]puis descend dansfrontend/). HEALTHCHECKintégré sur/api/health.- Deux volumes déclarés :
/etc/wireguard(config WireGuard) et/var/lib/wireguard-ui(données applicatives).
docker/entrypoint.sh¶
#!/bin/sh
set -e
cd /app/backend
alembic upgrade head
cd /app
exec uvicorn backend.app.main:app --host 0.0.0.0 --port 8000 --workers 1
C'est ce script, et non main.py, qui applique les migrations de base de données à chaque démarrage du conteneur — voir Base de données & migrations. --workers 1 : un seul worker Uvicorn, cohérent avec le rate-limiter et le service WireGuard qui sont gérés en mémoire, par process (pas de coordination multi-worker prévue).
docker-compose.yaml (build local)¶
services:
wireguard-ui:
build:
context: .
dockerfile: Dockerfile
container_name: wireguard-ui
restart: unless-stopped
environment:
- LOG_LEVEL=${LOG_LEVEL:-INFO}
volumes:
- wg_config:/etc/wireguard
- wg_data:/var/lib/wireguard-ui
cap_add:
- NET_ADMIN
ports:
- 51820:51820/udp
- 8000:8000/tcp
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
volumes:
wg_config:
wg_data:
Ajouter des variables
Ce fichier ne définit que LOG_LEVEL. Ajoutez ADMIN_USERNAME, SECRET_KEY, etc. dans la section environment:, ou créez un fichier .env à côté du docker-compose.yaml (Docker Compose le charge automatiquement) — voir Variables d'environnement.
Séquence de démarrage du conteneur¶
sequenceDiagram
participant Docker
participant Entrypoint as entrypoint.sh
participant Alembic
participant Uvicorn
participant App as lifespan (main.py)
Docker->>Entrypoint: exécute /entrypoint.sh
Entrypoint->>Alembic: alembic upgrade head
Alembic-->>Entrypoint: schéma à jour
Entrypoint->>Uvicorn: exec uvicorn backend.app.main:app
Uvicorn->>App: lifespan startup
App->>App: seed_initial_data()
App->>App: auto_start_wireguard() si WIREGUARD_AUTOSTART
App-->>Uvicorn: prêt à recevoir des requêtes