# Docker et applications en conteneurs Docker fait tourner des applications prêtes à l'emploi : Portainer, Uptime Kuma, Gitea, Vaultwarden… Chaque conteneur écoute **uniquement sur 127.0.0.1**, et Nginx de HestiaCP le publie sur un sous-domaine avec un certificat Let's Encrypt. > [!DANGER] Docker contourne le pare-feu > Un port publié par Docker (`-p 9000:9000`) passe **avant** le pare-feu de HestiaCP et devient accessible depuis Internet. Publiez toujours sur `127.0.0.1:` ; la configuration ci-dessous l'impose par défaut. ## Installer Docker (dépôt officiel) Ces commandes viennent de la documentation officielle de Docker pour Ubuntu : ```bash sudo apt update sudo apt install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc sudo tee /etc/apt/sources.list.d/docker.sources < [!CHECK] > `sudo docker run --rm hello-world` affiche `Hello from Docker!`, et `docker compose version` affiche une version 2.x ou plus. ## Configurer Docker : localhost et rotation des journaux Ce fichier fait publier les ports sur `127.0.0.1` par défaut, et limite la taille des journaux des conteneurs, qui peuvent sinon remplir le disque : ```bash sudo tee /etc/docker/daemon.json > /dev/null << 'EOF' { "ip": "127.0.0.1", "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } EOF sudo systemctl restart docker sudo systemctl enable docker containerd ``` Autorisez votre utilisateur à utiliser Docker sans `sudo`, puis déconnectez-vous et reconnectez-vous : ```bash sudo usermod -aG docker {{USER}} ``` > [!WARNING] > Le groupe `docker` donne des droits équivalents à root. Ne l'accordez qu'à {{USER}}, jamais à {{CLIENT}}. > [!NOTE] Pare-feu HestiaCP et Docker > `v-update-firewall` ne touche pas aux règles de Docker. En revanche, `sudo systemctl restart hestia-iptables` recharge un ancien instantané des règles : lancez `sudo systemctl restart docker` juste après. ## Créer le générateur de modèles de proxy HestiaCP publie un site à l'aide de **modèles Nginx**. Ce petit script crée un modèle `proxy-` qui redirige un domaine vers `127.0.0.1:`. Il gère le HTTPS forcé, HSTS, Let's Encrypt et les WebSockets. D'abord, la variable Nginx nécessaire aux WebSockets : ```bash sudo tee /etc/nginx/conf.d/websocket-map.conf > /dev/null << 'EOF' map $http_upgrade $connection_upgrade { default upgrade; '' close; } EOF sudo nginx -t && sudo systemctl reload nginx ``` Puis le générateur : ```bash sudo tee /usr/local/sbin/hestia-proxy-tpl > /dev/null << 'SCRIPT' #!/bin/bash # Usage : hestia-proxy-tpl PORT -> crée le modèle proxy Nginx "proxy-PORT" set -euo pipefail PORT="${1:?Usage : hestia-proxy-tpl PORT}" [[ "$PORT" =~ ^[0-9]{2,5}$ ]] || { echo "Port invalide : $PORT"; exit 1; } DIR=/usr/local/hestia/data/templates/web/nginx NAME="proxy-$PORT" LOCATION=' location / { proxy_pass http://127.0.0.1:__PORT__; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_read_timeout 3600s; proxy_send_timeout 3600s; client_max_body_size 512m; } location /error/ { alias %home%/%user%/web/%domain%/document_errors/; } ' cat > "$DIR/$NAME.tpl" << EOF # Modèle généré par hestia-proxy-tpl : proxy vers 127.0.0.1:__PORT__ server { listen %ip%:%proxy_port%; server_name %domain_idn% %alias_idn%; access_log /var/log/%web_system%/domains/%domain%.log combined; error_log /var/log/%web_system%/domains/%domain%.error.log error; include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*; $LOCATION include %home%/%user%/conf/web/%domain%/nginx.conf_*; } EOF cat > "$DIR/$NAME.stpl" << EOF # Modèle généré par hestia-proxy-tpl : proxy vers 127.0.0.1:__PORT__ server { listen %ip%:%proxy_ssl_port% ssl; server_name %domain_idn% %alias_idn%; access_log /var/log/%web_system%/domains/%domain%.log combined; error_log /var/log/%web_system%/domains/%domain%.error.log error; ssl_certificate %ssl_pem%; ssl_certificate_key %ssl_key%; if (\$anti_replay = 307) { return 307 https://\$host\$request_uri; } if (\$anti_replay = 425) { return 425; } include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*; $LOCATION include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*; } EOF sed -i "s/__PORT__/$PORT/g" "$DIR/$NAME.tpl" "$DIR/$NAME.stpl" chmod 644 "$DIR/$NAME.tpl" "$DIR/$NAME.stpl" echo "Modèle $NAME créé." SCRIPT sudo chmod 750 /usr/local/sbin/hestia-proxy-tpl ``` > [!NOTE] > Les modèles portent des noms personnels (`proxy-9000`…) : les mises à jour de HestiaCP ne les écrasent pas. Ne modifiez jamais les modèles `default`. ## Publier une application : la méthode Pour chaque application, le même schéma en 5 commandes. Exemple : un conteneur sur le port `PORT`, publié sur `appli.{{DOMAINE}}`. ```bash sudo hestia-proxy-tpl PORT sudo v-add-dns-record {{CLIENT}} {{DOMAINE}} appli A {{IP}} sudo v-add-web-domain {{CLIENT}} appli.{{DOMAINE}} sudo v-change-web-domain-proxy-tpl {{CLIENT}} appli.{{DOMAINE}} proxy-PORT sudo v-add-letsencrypt-domain {{CLIENT}} appli.{{DOMAINE}} sudo v-add-web-domain-ssl-force {{CLIENT}} appli.{{DOMAINE}} ``` ## Installer Portainer (gestion de Docker) Portainer est une interface web pour gérer vos conteneurs. On utilise son port HTTP 9000, uniquement sur localhost, derrière le proxy HTTPS : ```bash docker volume create portainer_data docker run -d --name portainer --restart=always \ -p 127.0.0.1:9000:9000 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce:lts ``` Publiez-le sur `portainer.{{DOMAINE}}` : ```bash sudo hestia-proxy-tpl 9000 sudo v-add-dns-record {{CLIENT}} {{DOMAINE}} portainer A {{IP}} sudo v-add-web-domain {{CLIENT}} portainer.{{DOMAINE}} sudo v-change-web-domain-proxy-tpl {{CLIENT}} portainer.{{DOMAINE}} proxy-9000 sudo v-add-letsencrypt-domain {{CLIENT}} portainer.{{DOMAINE}} sudo v-add-web-domain-ssl-force {{CLIENT}} portainer.{{DOMAINE}} ``` > [!WARNING] Créez le compte tout de suite > Ouvrez `https://portainer.{{DOMAINE}}` **dans les 5 minutes** et créez le compte administrateur avec un mot de passe fort. Passé ce délai, Portainer se verrouille par sécurité : relancez-le avec `docker restart portainer`. > [!CHECK] > `ss -tlnp | grep 9000` montre `127.0.0.1:9000` (et non `0.0.0.0:9000`), et `https://portainer.{{DOMAINE}}` affiche Portainer avec un cadenas valide. ## Utiliser Docker Compose pour les autres applications Pour une application décrite par un `compose.yaml`, placez-la dans `/opt//` et publiez toujours ses ports sur `127.0.0.1` : ```yaml services: appli: image: editeur/appli:version restart: unless-stopped ports: - "127.0.0.1:8080:8080" volumes: - ./data:/data ``` ```bash cd /opt/appli && docker compose up -d ``` Suivez ensuite la méthode ci-dessus avec le port `8080`. > [!TIP] Mettre à jour un conteneur > Avec Compose : `docker compose pull && docker compose up -d`. Portainer propose aussi un bouton **Recreate › Pull latest image**.