From 31fd2c3c8bf2900f3e8960b561829f90beef30c6 Mon Sep 17 00:00:00 2001 From: ncantu Date: Wed, 28 Jan 2026 11:48:25 +0100 Subject: [PATCH] Fix: Improve Docker services automatic startup and restart order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Motivations:** - Docker services (bitcoind and mempool) were not starting automatically after reboot - Mempool API was unhealthy because it tried to connect to bitcoind before it was ready - No restart policy for bitcoind container - Restart script started mempool before bitcoind, causing connection errors **Root causes:** - Bitcoind container had no restart policy (restart: no) - Restart script started mempool before bitcoind - No wait for bitcoind RPC to be ready before starting mempool - No boot startup script for Docker services **Correctifs:** - Configured restart policy for bitcoind container: docker update --restart=always - Improved restart-services-cron.sh: - Start/restart bitcoind BEFORE mempool - Wait for bitcoind RPC to be ready (max 60s) before starting mempool - Detect if container is stopped (start) or running (restart) - Use 'docker compose up -d' for mempool instead of 'restart' - Created start-docker-services.sh: - Start bitcoind first - Wait for bitcoind RPC to be ready (max 120s at boot) - Start mempool after bitcoind - Logging to data/start-docker-services.log - Created docker-services.service: - Systemd service to start Docker services at boot - Runs after docker.service and network.target - Executes start-docker-services.sh **Evolutions:** - Automatic startup at boot: Docker services start automatically after reboot - Guaranteed startup order: Bitcoind always starts before mempool - Availability check: Wait for bitcoind to be ready before starting mempool - Restart policy: Bitcoind container restarts automatically if stopped - Better observability: Detailed logs for diagnosis **Pages affectées:** - data/restart-services-cron.sh: Improved startup order and availability checks - data/start-docker-services.sh: New boot startup script - data/docker-services.service: New systemd service for automatic startup - fixKnowledge/docker-services-boot-startup.md: Documentation of improvements --- data/docker-services.service | 20 ++ data/restart-services-cron.sh | 65 +++++-- data/start-docker-services.sh | 73 ++++++++ fixKnowledge/docker-services-boot-startup.md | 183 +++++++++++++++++++ 4 files changed, 324 insertions(+), 17 deletions(-) create mode 100644 data/docker-services.service create mode 100755 data/start-docker-services.sh create mode 100644 fixKnowledge/docker-services-boot-startup.md diff --git a/data/docker-services.service b/data/docker-services.service new file mode 100644 index 0000000..5c3bf28 --- /dev/null +++ b/data/docker-services.service @@ -0,0 +1,20 @@ +[Unit] +Description=Start Docker services (bitcoind and mempool) at boot +After=docker.service network.target +Requires=docker.service + +[Service] +Type=oneshot +RemainAfterExit=yes +User=ncantu +WorkingDirectory=/home/ncantu/Bureau/code/bitcoin +ExecStart=/home/ncantu/Bureau/code/bitcoin/data/start-docker-services.sh +StandardOutput=journal +StandardError=journal + +# Security +NoNewPrivileges=true +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/data/restart-services-cron.sh b/data/restart-services-cron.sh index 8ed3c02..8b92df4 100755 --- a/data/restart-services-cron.sh +++ b/data/restart-services-cron.sh @@ -62,14 +62,57 @@ for u in "${restarted[@]}"; do fi done -# 4. Docker: mempool stack (local only) +# 4. Docker: bitcoind container (local only) - START FIRST +# Bitcoind must be running before mempool can connect to it +if docker ps -a -q -f "name=^${BITCOIND_CONTAINER}$" 2>/dev/null | grep -q .; then + log "Starting/restarting $BITCOIND_CONTAINER..." + bitcoind_ok=0 + if docker ps -q -f "name=^${BITCOIND_CONTAINER}$" 2>/dev/null | grep -q .; then + # Container is running, just restart it + if docker restart "$BITCOIND_CONTAINER" &>/dev/null; then + bitcoind_ok=1 + fi + else + # Container exists but is stopped, start it + if docker start "$BITCOIND_CONTAINER" &>/dev/null; then + bitcoind_ok=1 + fi + fi + + if [ "$bitcoind_ok" -eq 1 ]; then + log " $BITCOIND_CONTAINER started, waiting for RPC to be ready..." + # Wait for bitcoind RPC to be ready (max 60 seconds) + max_wait=60 + wait_count=0 + while [ $wait_count -lt $max_wait ]; do + if docker exec "$BITCOIND_CONTAINER" bitcoin-cli -datadir=/root/.bitcoin getblockchaininfo &>/dev/null; then + log " $BITCOIND_CONTAINER RPC ready" + break + fi + sleep 1 + wait_count=$((wait_count + 1)) + done + if [ $wait_count -ge $max_wait ]; then + log " WARN: $BITCOIND_CONTAINER RPC not ready after ${max_wait}s" + fi + else + log " $BITCOIND_CONTAINER FAILED" + fi +else + log "SKIP: $BITCOIND_CONTAINER container not found (bitcoind may run as systemd)" +fi + +# 5. Docker: mempool stack (local only) - START AFTER BITCOIND +# Mempool depends on bitcoind being ready if [ -f "$MEMPOOL_COMPOSE" ] && command -v docker &>/dev/null; then - log "Restarting mempool (docker)..." + log "Starting/restarting mempool (docker)..." mem_ok=1 - (cd "${PROJECT_DIR}/mempool" && docker compose -f docker-compose.signet.yml restart &>/dev/null) && mem_ok=0 - [ "$mem_ok" -ne 0 ] && (cd "${PROJECT_DIR}/mempool" && docker-compose -f docker-compose.signet.yml restart &>/dev/null) && mem_ok=0 + (cd "${PROJECT_DIR}/mempool" && docker compose -f docker-compose.signet.yml up -d &>/dev/null) && mem_ok=0 + [ "$mem_ok" -ne 0 ] && (cd "${PROJECT_DIR}/mempool" && docker-compose -f docker-compose.signet.yml up -d &>/dev/null) && mem_ok=0 if [ "$mem_ok" -eq 0 ]; then - log " mempool OK" + log " mempool started" + # Wait a bit for mempool to initialize + sleep 5 else log " mempool FAILED" fi @@ -81,17 +124,5 @@ else fi fi -# 5. Docker: bitcoind container (local only) -if docker ps -a -q -f "name=^${BITCOIND_CONTAINER}$" 2>/dev/null | grep -q .; then - log "Restarting $BITCOIND_CONTAINER..." - if docker restart "$BITCOIND_CONTAINER" &>/dev/null; then - log " $BITCOIND_CONTAINER OK" - else - log " $BITCOIND_CONTAINER FAILED" - fi -else - log "SKIP: $BITCOIND_CONTAINER container not found (bitcoind may run as systemd)" -fi - log "=== Done ===" tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE" diff --git a/data/start-docker-services.sh b/data/start-docker-services.sh new file mode 100755 index 0000000..e3a2463 --- /dev/null +++ b/data/start-docker-services.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# Start Docker services at boot (bitcoind and mempool). +# This script ensures bitcoind starts before mempool. +# Can be called from systemd service or cron @reboot. +# Log: data/start-docker-services.log +# +# Local only: no SSH, no remote commands. + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +LOG_FILE="$SCRIPT_DIR/start-docker-services.log" +MEMPOOL_COMPOSE="${PROJECT_DIR}/mempool/docker-compose.signet.yml" +BITCOIND_CONTAINER="bitcoin-signet-instance" + +log() { echo "$(date -Iseconds) $*" | tee -a "$LOG_FILE"; } + +cd "$PROJECT_DIR" || exit 1 + +log "=== Start Docker services at boot ===" + +# Check if docker is available +if ! command -v docker &>/dev/null; then + log "ERROR: docker command not found" + exit 1 +fi + +# 1. Start bitcoind container (must be first) +if docker ps -a -q -f "name=^${BITCOIND_CONTAINER}$" 2>/dev/null | grep -q .; then + if docker ps -q -f "name=^${BITCOIND_CONTAINER}$" 2>/dev/null | grep -q .; then + log "$BITCOIND_CONTAINER already running" + else + log "Starting $BITCOIND_CONTAINER..." + if docker start "$BITCOIND_CONTAINER" &>/dev/null; then + log " $BITCOIND_CONTAINER started" + # Wait for bitcoind RPC to be ready (max 120 seconds at boot) + max_wait=120 + wait_count=0 + while [ $wait_count -lt $max_wait ]; do + if docker exec "$BITCOIND_CONTAINER" bitcoin-cli -datadir=/root/.bitcoin getblockchaininfo &>/dev/null; then + log " $BITCOIND_CONTAINER RPC ready after ${wait_count}s" + break + fi + sleep 2 + wait_count=$((wait_count + 2)) + done + if [ $wait_count -ge $max_wait ]; then + log " WARN: $BITCOIND_CONTAINER RPC not ready after ${max_wait}s (may still be starting)" + fi + else + log " ERROR: Failed to start $BITCOIND_CONTAINER" + fi + fi +else + log "SKIP: $BITCOIND_CONTAINER container not found" +fi + +# 2. Start mempool stack (after bitcoind) +if [ -f "$MEMPOOL_COMPOSE" ]; then + log "Starting mempool stack..." + mem_ok=1 + (cd "${PROJECT_DIR}/mempool" && docker compose -f docker-compose.signet.yml up -d &>/dev/null) && mem_ok=0 + [ "$mem_ok" -ne 0 ] && (cd "${PROJECT_DIR}/mempool" && docker-compose -f docker-compose.signet.yml up -d &>/dev/null) && mem_ok=0 + if [ "$mem_ok" -eq 0 ]; then + log " mempool stack started" + else + log " ERROR: Failed to start mempool stack" + fi +else + log "SKIP: mempool compose not found" +fi + +log "=== Done ===" +tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE" diff --git a/fixKnowledge/docker-services-boot-startup.md b/fixKnowledge/docker-services-boot-startup.md new file mode 100644 index 0000000..1f542a9 --- /dev/null +++ b/fixKnowledge/docker-services-boot-startup.md @@ -0,0 +1,183 @@ +# Fix: Amélioration du démarrage automatique des services Docker (bitcoind et mempool) + +**Auteur** : Équipe 4NK +**Date** : 2026-01-28 +**Version** : 1.0 + +## Problème identifié + +Lors du redémarrage de la machine, les services Docker (bitcoind et mempool) ne démarraient pas automatiquement ou dans le bon ordre, causant : + +- Le conteneur `bitcoin-signet-instance` était arrêté après un reboot +- Le mempool API était unhealthy car il ne pouvait pas se connecter à bitcoind +- Aucune politique de redémarrage automatique pour le conteneur bitcoind +- Le script de redémarrage redémarrait mempool avant bitcoind, causant des erreurs de connexion + +### Symptômes + +- Après un reboot, `bitcoin-signet-instance` était arrêté (status: Exited) +- Le mempool API était unhealthy avec erreurs `connect ECONNREFUSED 172.17.0.1:38332` +- Les requêtes vers mempool retournaient 502 Bad Gateway +- Le script `restart-services-cron.sh` redémarrait mempool avant bitcoind + +### Impact + +- **Fonctionnalité** : Mempool ne fonctionnait pas après un reboot +- **Service** : Les ancrages Bitcoin ne pouvaient pas être vérifiés via mempool +- **Maintenance** : Intervention manuelle requise après chaque reboot + +## Root causes + +1. **Pas de restart policy** : Le conteneur `bitcoin-signet-instance` n'avait pas de politique de redémarrage automatique (`restart: no`) +2. **Ordre de démarrage incorrect** : Le script redémarrait mempool avant bitcoind, causant des erreurs de connexion +3. **Pas d'attente de disponibilité** : Le script ne vérifiait pas que bitcoind était prêt avant de démarrer mempool +4. **Pas de script de démarrage au boot** : Aucun mécanisme pour démarrer automatiquement les services Docker au boot + +## Correctifs appliqués + +### 1. Configuration de la restart policy pour bitcoind + +**Action** : Configuration de la politique de redémarrage automatique pour le conteneur bitcoind + +```bash +docker update --restart=always bitcoin-signet-instance +``` + +**Résultat** : Le conteneur redémarre automatiquement en cas d'arrêt ou après un reboot + +### 2. Amélioration du script `restart-services-cron.sh` + +**Fichier** : `data/restart-services-cron.sh` + +**Modifications** : +- **Ordre de démarrage** : Bitcoind est maintenant démarré/redémarré AVANT mempool +- **Vérification de disponibilité** : Attente que le RPC bitcoind soit prêt (max 60s) avant de démarrer mempool +- **Gestion des états** : Détection si le conteneur est arrêté (start) ou en cours d'exécution (restart) +- **Utilisation de `up -d`** : Utilisation de `docker compose up -d` au lieu de `restart` pour mempool (démarre si arrêté, redémarre si en cours) + +**Avant** : +```bash +# 4. Docker: mempool stack (redémarré avant bitcoind) +# 5. Docker: bitcoind container +``` + +**Après** : +```bash +# 4. Docker: bitcoind container (START FIRST) +# - Attente que RPC soit prêt (max 60s) +# 5. Docker: mempool stack (START AFTER BITCOIND) +``` + +### 3. Création du script `start-docker-services.sh` + +**Fichier** : `data/start-docker-services.sh` + +**Fonctionnalités** : +- Démarrage de bitcoind en premier +- Attente que le RPC bitcoind soit prêt (max 120s au boot) +- Démarrage de mempool après bitcoind +- Logging dans `data/start-docker-services.log` +- Rotation des logs (100 dernières lignes) + +**Usage** : Peut être appelé depuis un service systemd ou un cron `@reboot` + +### 4. Création du service systemd `docker-services.service` + +**Fichier** : `data/docker-services.service` + +**Configuration** : +- Démarre après `docker.service` et `network.target` +- Exécute `start-docker-services.sh` au boot +- Type `oneshot` avec `RemainAfterExit=yes` +- Logs via journald + +**Installation** : +```bash +sudo cp data/docker-services.service /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl enable docker-services +sudo systemctl start docker-services +``` + +## Modifications + +**Fichiers modifiés** : +- `data/restart-services-cron.sh` : Amélioration de l'ordre de démarrage et ajout de vérifications + +**Fichiers créés** : +- `data/start-docker-services.sh` : Script de démarrage au boot +- `data/docker-services.service` : Service systemd pour démarrage automatique +- `fixKnowledge/docker-services-boot-startup.md` : Cette documentation + +## Modalités de déploiement + +1. **Configurer la restart policy** (déjà fait) : + ```bash + docker update --restart=always bitcoin-signet-instance + ``` + +2. **Installer le service systemd** (optionnel mais recommandé) : + ```bash + sudo cp data/docker-services.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable docker-services + sudo systemctl start docker-services + ``` + +3. **Vérifier le fonctionnement** : + ```bash + # Vérifier que bitcoind redémarre automatiquement + docker restart bitcoin-signet-instance + docker ps | grep bitcoin-signet-instance + + # Vérifier que mempool démarre après bitcoind + sudo systemctl status docker-services + ``` + +4. **Tester après un reboot** : + ```bash + # Après reboot, vérifier + docker ps | grep -E "(bitcoin|mempool)" + curl http://localhost:3015/api/v1/blocks/tip/height + ``` + +## Modalités d'analyse + +- **Logs du service systemd** : + ```bash + sudo journalctl -u docker-services -f + ``` + +- **Logs du script** : + ```bash + tail -f data/start-docker-services.log + ``` + +- **Vérification des conteneurs** : + ```bash + docker ps --format "table {{.Names}}\t{{.Status}}" + docker inspect bitcoin-signet-instance --format='{{.HostConfig.RestartPolicy.Name}}' + ``` + +- **Vérification de la connectivité** : + ```bash + # Bitcoind RPC + docker exec bitcoin-signet-instance bitcoin-cli -datadir=/root/.bitcoin getblockchaininfo + + # Mempool API + curl http://localhost:3015/api/v1/blocks/tip/height + ``` + +## Evolutions + +- **Démarrage automatique au boot** : Les services Docker démarrent automatiquement après un reboot +- **Ordre de démarrage garanti** : Bitcoind démarre toujours avant mempool +- **Vérification de disponibilité** : Attente que bitcoind soit prêt avant de démarrer mempool +- **Restart policy** : Le conteneur bitcoind redémarre automatiquement en cas d'arrêt +- **Meilleure observabilité** : Logs détaillés pour le diagnostic + +## Références + +- Documentation existante : `features/cron-restart-services-local.md` +- Script de redémarrage : `data/restart-services-cron.sh` +- Script de démarrage : `data/start-docker-services.sh`