Fix: Improve Docker services automatic startup and restart order
**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
This commit is contained in:
parent
8662e9e584
commit
31fd2c3c8b
20
data/docker-services.service
Normal file
20
data/docker-services.service
Normal file
@ -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
|
||||||
@ -62,14 +62,57 @@ for u in "${restarted[@]}"; do
|
|||||||
fi
|
fi
|
||||||
done
|
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
|
if [ -f "$MEMPOOL_COMPOSE" ] && command -v docker &>/dev/null; then
|
||||||
log "Restarting mempool (docker)..."
|
log "Starting/restarting mempool (docker)..."
|
||||||
mem_ok=1
|
mem_ok=1
|
||||||
(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 restart &>/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
|
if [ "$mem_ok" -eq 0 ]; then
|
||||||
log " mempool OK"
|
log " mempool started"
|
||||||
|
# Wait a bit for mempool to initialize
|
||||||
|
sleep 5
|
||||||
else
|
else
|
||||||
log " mempool FAILED"
|
log " mempool FAILED"
|
||||||
fi
|
fi
|
||||||
@ -81,17 +124,5 @@ else
|
|||||||
fi
|
fi
|
||||||
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 ==="
|
log "=== Done ==="
|
||||||
tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
|
tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
|
||||||
|
|||||||
73
data/start-docker-services.sh
Executable file
73
data/start-docker-services.sh
Executable file
@ -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"
|
||||||
183
fixKnowledge/docker-services-boot-startup.md
Normal file
183
fixKnowledge/docker-services-boot-startup.md
Normal file
@ -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`
|
||||||
Loading…
x
Reference in New Issue
Block a user