Installation, configuration et gestion avancée de vos environnements Docker
Portainer est une interface web légère et intuitive pour gérer vos environnements Docker, Docker Swarm et Kubernetes. Il simplifie la gestion des conteneurs, images, volumes, réseaux et bien plus encore, tout en offrant des fonctionnalités avancées pour les environnements de production.
| Fonctionnalité | Community Edition (CE) | Enterprise Edition (EE) |
|---|---|---|
| Gestion Docker/Swarm | ✅ Complète | ✅ Complète |
| Support Kubernetes | ✅ Basique | ✅ Avancé |
| Authentification LDAP/OAuth | ❌ | ✅ |
| RBAC avancé | ❌ | ✅ |
| Support commercial | ❌ | ✅ |
| Audit logs | ❌ | ✅ |
Portainer CE est parfait pour les environnements de développement et les petites équipes. Pour les environnements de production avec des besoins de sécurité avancés, considérez Portainer EE.
Assurez-vous que Docker est installé et fonctionne :
# Vérification de la version Docker
docker --version
# Test de fonctionnement
docker run hello-world
# Vérification des informations système
docker system info
# Vérification de l'espace disque
docker system df
Ouvrez les ports nécessaires dans votre pare-feu :
# Port HTTP Portainer
sudo ufw allow 9000/tcp
# Port HTTPS Portainer
sudo ufw allow 9443/tcp
# Port pour agent Portainer (si nécessaire)
sudo ufw allow 9001/tcp
# Vérification des règles
sudo ufw status
Créez les répertoires pour les données persistantes :
# Création du répertoire pour les données Portainer
sudo mkdir -p /opt/portainer/data
# Permissions appropriées
sudo chown -R 1000:1000 /opt/portainer/data
# Création du répertoire pour les certificats SSL
sudo mkdir -p /opt/portainer/certs
# Vérification
ls -la /opt/portainer/
Installation simple de Portainer CE :
# Création du volume pour les données
docker volume create portainer_data
# Lancement de Portainer CE
docker run -d \
--name portainer \
--restart=always \
-p 8000:8000 \
-p 9000:9000 \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
# Vérification du conteneur
docker ps | grep portainer
Configuration plus avancée avec Docker Compose :
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- "8000:8000"
- "9000:9000"
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- portainer_data:/data
- /opt/portainer/certs:/certs:ro
environment:
- PORTAINER_ADMIN_PASSWORD_FILE=/run/secrets/portainer_admin_password
secrets:
- portainer_admin_password
command: >
--admin-password-file /run/secrets/portainer_admin_password
--ssl
--sslcert /certs/portainer.crt
--sslkey /certs/portainer.key
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9000/api/status"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
portainer_data:
driver: local
secrets:
portainer_admin_password:
file: ./portainer_admin_password.txt
Génération et configuration des certificats SSL :
# Génération de la clé privée
openssl genrsa -out /opt/portainer/certs/portainer.key 4096
# Génération du certificat auto-signé
openssl req -new -x509 -key /opt/portainer/certs/portainer.key \
-out /opt/portainer/certs/portainer.crt -days 365 \
-subj "/C=FR/ST=IDF/L=Paris/O=MonEntreprise/CN=portainer.domain.local"
# Permissions sécurisées
chmod 600 /opt/portainer/certs/portainer.key
chmod 644 /opt/portainer/certs/portainer.crt
# Création du fichier de mot de passe admin
echo 'MonMotDePasseSecurise123!' > ./portainer_admin_password.txt
chmod 600 ./portainer_admin_password.txt
# Lancement avec Docker Compose
docker-compose up -d
Portainer est maintenant accessible à l'adresse : https://votre-serveur:9443 ou http://votre-serveur:9000
Configuration d'un cluster Docker Swarm :
# Initialisation du Swarm (sur le manager principal)
docker swarm init --advertise-addr $(hostname -I | awk '{print $1}')
# Récupération du token pour les workers
docker swarm join-token worker
# Récupération du token pour les managers
docker swarm join-token manager
# Vérification du cluster
docker node ls
Déploiement de Portainer en tant que service Swarm :
version: '3.8'
services:
agent:
image: portainer/agent:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
networks:
- agent_network
deploy:
mode: global
placement:
constraints: [node.platform.os == linux]
resources:
limits:
memory: 128M
reservations:
memory: 64M
portainer:
image: portainer/portainer-ce:latest
command: -H tcp://tasks.agent:9001 --tlsskipverify
ports:
- "9000:9000"
- "9443:9443"
- "8000:8000"
volumes:
- portainer_data:/data
networks:
- agent_network
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.role == manager]
resources:
limits:
memory: 512M
reservations:
memory: 256M
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
monitor: 60s
max_failure_ratio: 0.3
networks:
agent_network:
driver: overlay
attachable: true
volumes:
portainer_data:
driver: local
# Déploiement de la stack Portainer
docker stack deploy -c portainer-swarm-stack.yml portainer
# Vérification du déploiement
docker stack ls
docker stack services portainer
docker service logs portainer_portainer
# Vérification des agents
docker service ps portainer_agent
Dans cette configuration, Portainer Agent s'exécute sur chaque nœud du cluster, permettant à Portainer de gérer l'ensemble du Swarm depuis une interface centralisée.
Méthode recommandée avec Helm Chart :
# Ajout du repository Helm Portainer
helm repo add portainer https://portainer.github.io/k8s/
helm repo update
# Installation de Portainer
helm install portainer portainer/portainer \
--create-namespace \
--namespace portainer \
--set service.type=LoadBalancer \
--set tls.force=true
# Vérification du déploiement
kubectl get all -n portainer
# Récupération de l'IP externe
kubectl get svc -n portainer
Déploiement manuel avec des manifestes Kubernetes :
apiVersion: v1
kind: Namespace
metadata:
name: portainer
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: portainer-sa-clusteradmin
namespace: portainer
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: portainer-crb-clusteradmin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: portainer-sa-clusteradmin
namespace: portainer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: portainer-pvc
namespace: portainer
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: portainer
namespace: portainer
spec:
replicas: 1
selector:
matchLabels:
app: portainer
template:
metadata:
labels:
app: portainer
spec:
serviceAccountName: portainer-sa-clusteradmin
containers:
- name: portainer
image: portainer/portainer-ce:latest
ports:
- containerPort: 9000
- containerPort: 9443
- containerPort: 8000
volumeMounts:
- name: data
mountPath: /data
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
livenessProbe:
httpGet:
path: /api/status
port: 9000
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /api/status
port: 9000
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: data
persistentVolumeClaim:
claimName: portainer-pvc
---
apiVersion: v1
kind: Service
metadata:
name: portainer
namespace: portainer
spec:
type: LoadBalancer
ports:
- port: 9000
targetPort: 9000
name: http
- port: 9443
targetPort: 9443
name: https
- port: 8000
targetPort: 8000
name: edge
selector:
app: portainer
# Application des manifestes
kubectl apply -f portainer-k8s.yaml
# Vérification du déploiement
kubectl get pods -n portainer
kubectl get svc -n portainer
# Vérification des logs
kubectl logs -n portainer deployment/portainer
# Port-forward pour accès local (si pas de LoadBalancer)
kubectl port-forward -n portainer svc/portainer 9000:9000 9443:9443
Lors du premier accès à Portainer :
Vous avez 5 minutes après le démarrage de Portainer pour créer le compte administrateur. Passé ce délai, le conteneur se ferme pour des raisons de sécurité.
http://votre-serveur:9000 ou https://votre-serveur:9443Sélection et configuration de votre environnement :
# Script de configuration automatique
#!/bin/bash
PORTAINER_URL="https://localhost:9443"
USERNAME="admin"
PASSWORD="VotreMotDePasse"
# Authentification et récupération du token
TOKEN=$(curl -s -X POST "$PORTAINER_URL/api/auth" \
-H "Content-Type: application/json" \
-d "{\"Username\":\"$USERNAME\",\"Password\":\"$PASSWORD\"}" \
--insecure | jq -r '.jwt')
# Configuration des paramètres globaux
curl -X PUT "$PORTAINER_URL/api/settings" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"LogoURL": "",
"BlackListedLabels": [],
"AuthenticationMethod": 1,
"LDAPSettings": {
"ReaderDN": "",
"Password": "",
"URL": "",
"TLSConfig": {
"TLS": false,
"TLSSkipVerify": false
},
"StartTLS": false,
"SearchSettings": [
{
"BaseDN": "",
"Filter": "",
"UserNameAttribute": ""
}
],
"GroupSearchSettings": [
{
"GroupBaseDN": "",
"GroupFilter": "",
"GroupAttribute": ""
}
]
},
"AllowBindMountsForRegularUsers": false,
"AllowPrivilegedModeForRegularUsers": false,
"AllowVolumeBrowserForRegularUsers": false,
"AllowHostNamespaceForRegularUsers": false,
"AllowStackManagementForRegularUsers": true,
"AllowDeviceMappingForRegularUsers": false,
"AllowContainerCapabilitiesForRegularUsers": false,
"EnableHostManagementFeatures": false,
"EdgeAgentCheckinInterval": 5
}' \
--insecure
Configuration automatique avec Certbot :
# Installation de Certbot
sudo apt install -y certbot python3-certbot-nginx
# Génération du certificat
sudo certbot --nginx -d portainer.votre-domaine.com
# Configuration Nginx pour Portainer
cat > /etc/nginx/sites-available/portainer << 'EOF'
server {
listen 80;
server_name portainer.votre-domaine.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name portainer.votre-domaine.com;
ssl_certificate /etc/letsencrypt/live/portainer.votre-domaine.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/portainer.votre-domaine.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
proxy_pass http://localhost:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
proxy_read_timeout 86400;
}
}
EOF
# Activation du site
sudo ln -s /etc/nginx/sites-available/portainer /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
# Configuration Docker avec restriction IP
docker run -d \
--name portainer \
--restart=always \
-p 127.0.0.1:9000:9000 \
-p 127.0.0.1:9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
# Configuration UFW pour restriction
sudo ufw deny 9000
sudo ufw deny 9443
sudo ufw allow from 192.168.1.0/24 to any port 9000
sudo ufw allow from 192.168.1.0/24 to any port 9443
# Fail2ban pour Portainer
cat > /etc/fail2ban/jail.d/portainer.conf << 'EOF'
[portainer]
enabled = true
port = 9000,9443
filter = portainer
logpath = /var/lib/docker/containers/*/portainer*-json.log
maxretry = 3
bantime = 3600
findtime = 600
EOF
# Filtre Fail2ban
cat > /etc/fail2ban/filter.d/portainer.conf << 'EOF'
[Definition]
failregex = .*Invalid credentials.*.*
ignoreregex =
EOF
sudo systemctl restart fail2ban
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
# Sécurité renforcée
security_opt:
- no-new-privileges:true
- apparmor:docker-default
# Utilisateur non-root
user: "1000:1000"
# Limitations de ressources
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'
# Réseau personnalisé
networks:
- portainer_network
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- portainer_data:/data
- /opt/portainer/certs:/certs:ro
environment:
- PORTAINER_ADMIN_PASSWORD_FILE=/run/secrets/portainer_admin_password
secrets:
- portainer_admin_password
command: >
--admin-password-file /run/secrets/portainer_admin_password
--ssl
--sslcert /certs/portainer.crt
--sslkey /certs/portainer.key
--hide-label owner=system
--logo "https://votre-domaine.com/logo.png"
networks:
portainer_network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
portainer_data:
driver: local
secrets:
portainer_admin_password:
file: ./portainer_admin_password.txt
Installation d'agents sur des serveurs distants :
# Sur le serveur distant - Installation de l'agent
docker run -d \
--name portainer_agent \
--restart=always \
-p 9001:9001 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
portainer/agent:latest
# Vérification de l'agent
docker logs portainer_agent
# Test de connectivité
curl http://serveur-distant:9001/ping
Configuration pour des environnements sans connectivité directe :
# Génération de la commande Edge Agent depuis Portainer UI
# Environments > Add environment > Edge Agent
# Exemple de commande générée
docker run -d \
--name portainer_edge_agent \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
-v /:/host \
-v portainer_agent_data:/data \
--label "io.portainer.agent=true" \
-e EDGE=1 \
-e EDGE_ID=votre-edge-id \
-e EDGE_KEY=votre-edge-key \
-e CAP_HOST_MANAGEMENT=1 \
portainer/agent:latest
# Configuration du tunnel (si nécessaire)
# Pour les environnements derrière NAT/Firewall
#!/bin/bash
# portainer-multi-env-setup.sh
PORTAINER_URL="https://portainer.votre-domaine.com"
USERNAME="admin"
PASSWORD="VotreMotDePasse"
# Liste des environnements à ajouter
declare -A ENVIRONMENTS=(
["prod-web"]="tcp://prod-web.domain.com:2376"
["staging"]="tcp://staging.domain.com:2376"
["dev"]="tcp://dev.domain.com:2376"
)
# Authentification
TOKEN=$(curl -s -X POST "$PORTAINER_URL/api/auth" \
-H "Content-Type: application/json" \
-d "{\"Username\":\"$USERNAME\",\"Password\":\"$PASSWORD\"}" \
--insecure | jq -r '.jwt')
# Fonction pour ajouter un environnement
add_environment() {
local name=$1
local url=$2
echo "Ajout de l'environnement: $name ($url)"
curl -s -X POST "$PORTAINER_URL/api/endpoints" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"Name\": \"$name\",
\"URL\": \"$url\",
\"EndpointCreationType\": 1,
\"TLS\": true,
\"TLSSkipVerify\": true
}" \
--insecure
}
# Ajout de tous les environnements
for env_name in "${!ENVIRONMENTS[@]}"; do
add_environment "$env_name" "${ENVIRONMENTS[$env_name]}"
sleep 2
done
echo "Configuration multi-environnements terminée!"
L'authentification LDAP/OAuth n'est disponible que dans Portainer Enterprise Edition. Voici la configuration pour référence.
# Configuration LDAP via API
curl -X PUT "$PORTAINER_URL/api/settings" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"AuthenticationMethod": 2,
"LDAPSettings": {
"ReaderDN": "cn=portainer,ou=services,dc=domain,dc=local",
"Password": "password-service-account",
"URL": "ldap://dc.domain.local:389",
"TLSConfig": {
"TLS": false,
"TLSSkipVerify": false
},
"StartTLS": false,
"SearchSettings": [
{
"BaseDN": "ou=users,dc=domain,dc=local",
"Filter": "(&(objectClass=person)(uid={{.Username}}))",
"UserNameAttribute": "uid"
}
],
"GroupSearchSettings": [
{
"GroupBaseDN": "ou=groups,dc=domain,dc=local",
"GroupFilter": "(&(objectClass=groupOfNames)(member={{.UserDN}}))",
"GroupAttribute": "cn"
}
]
}
}' \
--insecure
# Configuration OAuth GitHub
curl -X PUT "$PORTAINER_URL/api/settings" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"AuthenticationMethod": 3,
"OAuthSettings": {
"ClientID": "votre-github-client-id",
"ClientSecret": "votre-github-client-secret",
"AuthorizationURI": "https://github.com/login/oauth/authorize",
"AccessTokenURI": "https://github.com/login/oauth/access_token",
"ResourceURI": "https://api.github.com/user",
"RedirectURI": "https://portainer.votre-domaine.com",
"UserIdentifier": "login",
"Scopes": "user:email",
"OAuthAutoCreateUsers": true,
"DefaultTeamID": 1
}
}' \
--insecure
#!/bin/bash
# portainer-backup.sh
BACKUP_DIR="/backup/portainer"
DATE=$(date +%Y%m%d_%H%M%S)
CONTAINER_NAME="portainer"
# Création du répertoire de sauvegarde
mkdir -p "$BACKUP_DIR/$DATE"
# Arrêt temporaire de Portainer
echo "Arrêt de Portainer..."
docker stop $CONTAINER_NAME
# Sauvegarde du volume de données
echo "Sauvegarde des données..."
docker run --rm \
-v portainer_data:/data \
-v "$BACKUP_DIR/$DATE":/backup \
alpine tar czf /backup/portainer-data.tar.gz -C /data .
# Sauvegarde de la configuration Docker Compose
if [ -f "docker-compose.yml" ]; then
cp docker-compose.yml "$BACKUP_DIR/$DATE/"
fi
# Sauvegarde des certificats
if [ -d "/opt/portainer/certs" ]; then
tar czf "$BACKUP_DIR/$DATE/certs.tar.gz" -C /opt/portainer certs
fi
# Redémarrage de Portainer
echo "Redémarrage de Portainer..."
docker start $CONTAINER_NAME
# Nettoyage des anciennes sauvegardes (garde 30 jours)
find "$BACKUP_DIR" -type d -mtime +30 -exec rm -rf {} \;
echo "Sauvegarde terminée: $BACKUP_DIR/$DATE"
#!/bin/bash
# portainer-restore.sh
BACKUP_PATH=$1
CONTAINER_NAME="portainer"
if [ -z "$BACKUP_PATH" ]; then
echo "Usage: $0 /path/to/backup/directory"
exit 1
fi
# Arrêt de Portainer
echo "Arrêt de Portainer..."
docker stop $CONTAINER_NAME
docker rm $CONTAINER_NAME
# Suppression de l'ancien volume
docker volume rm portainer_data
# Création d'un nouveau volume
docker volume create portainer_data
# Restauration des données
echo "Restauration des données..."
docker run --rm \
-v portainer_data:/data \
-v "$BACKUP_PATH":/backup \
alpine tar xzf /backup/portainer-data.tar.gz -C /data
# Restauration des certificats
if [ -f "$BACKUP_PATH/certs.tar.gz" ]; then
echo "Restauration des certificats..."
tar xzf "$BACKUP_PATH/certs.tar.gz" -C /opt/portainer/
fi
# Redémarrage de Portainer
echo "Redémarrage de Portainer..."
if [ -f "$BACKUP_PATH/docker-compose.yml" ]; then
cp "$BACKUP_PATH/docker-compose.yml" .
docker-compose up -d
else
docker run -d \
--name portainer \
--restart=always \
-p 9000:9000 \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
fi
echo "Restauration terminée!"
# Ajout au crontab
sudo crontab -e
# Sauvegarde quotidienne à 2h du matin
0 2 * * * /usr/local/bin/portainer-backup.sh
# Sauvegarde hebdomadaire avec notification
0 3 * * 0 /usr/local/bin/portainer-backup.sh && echo "Sauvegarde Portainer réussie" | mail -s "Backup Success" admin@domain.com
# Vérification de l'intégrité des sauvegardes
0 4 * * * find /backup/portainer -name "*.tar.gz" -mtime -1 -exec tar -tzf {} \; > /dev/null || echo "Erreur sauvegarde Portainer" | mail -s "Backup Error" admin@domain.com
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
ports:
- "9000:9000"
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
networks:
- monitoring
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
volumes:
- grafana_data:/var/lib/grafana
networks:
- monitoring
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
networks:
- monitoring
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
networks:
- monitoring
networks:
monitoring:
driver: bridge
volumes:
portainer_data:
prometheus_data:
grafana_data:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "portainer_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'portainer'
static_configs:
- targets: ['portainer:9000']
metrics_path: '/api/status'
scrape_interval: 30s
groups:
- name: portainer_alerts
rules:
- alert: PortainerDown
expr: up{job="portainer"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Portainer is down"
description: "Portainer has been down for more than 1 minute."
- alert: HighContainerCount
expr: count(container_last_seen) > 100
for: 5m
labels:
severity: warning
annotations:
summary: "High number of containers"
description: "More than 100 containers are running."
- alert: HighMemoryUsage
expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes > 0.9
for: 2m
labels:
severity: warning
annotations:
summary: "High memory usage"
description: "Memory usage is above 90%."
- alert: HighDiskUsage
expr: (node_filesystem_size_bytes{fstype!="tmpfs"} - node_filesystem_free_bytes{fstype!="tmpfs"}) / node_filesystem_size_bytes{fstype!="tmpfs"} > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "High disk usage"
description: "Disk usage is above 80%."
Symptômes : Le conteneur Portainer s'arrête immédiatement
# Vérification des logs
docker logs portainer
# Vérification des permissions du socket Docker
ls -la /var/run/docker.sock
# Vérification de l'espace disque
df -h
# Test de connectivité Docker
docker version
# Vérification des ports
netstat -tlnp | grep -E "(9000|9443)"
# Redémarrage avec debug
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest --log-level=DEBUG
Symptômes : Impossible de se connecter aux environnements distants
# Test de connectivité vers l'agent
curl -v http://serveur-distant:9001/ping
# Vérification des certificats TLS
openssl s_client -connect serveur-distant:2376 -showcerts
# Test Docker API
curl -k https://serveur-distant:2376/version
# Vérification des règles de pare-feu
sudo ufw status
sudo iptables -L
# Test depuis le conteneur Portainer
docker exec -it portainer sh
wget -qO- http://serveur-distant:9001/ping
# Vérification des ressources du conteneur
docker stats portainer
# Augmentation des limites de ressources
docker update --memory=1g --cpus=1.0 portainer
# Nettoyage des données inutiles
docker exec -it portainer sh -c "find /data -name '*.log' -mtime +7 -delete"
# Optimisation de la base de données
docker exec -it portainer sh -c "sqlite3 /data/portainer.db 'VACUUM;'"
# Redémarrage avec plus de mémoire
docker stop portainer
docker rm portainer
docker run -d \
--name portainer \
--restart=always \
--memory=1g \
--cpus=1.0 \
-p 9000:9000 \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
#!/bin/bash
# portainer-diagnostic.sh
echo "=== DIAGNOSTIC PORTAINER ==="
echo "Date: $(date)"
echo "Hostname: $(hostname)"
echo
# Vérification Docker
echo "=== DOCKER ==="
docker --version
docker info | grep -E "(Server Version|Storage Driver|Logging Driver)"
echo
# Vérification Portainer
echo "=== PORTAINER ==="
if docker ps | grep -q portainer; then
echo "✅ Portainer est en cours d'exécution"
docker ps | grep portainer
echo
echo "Logs récents:"
docker logs --tail 10 portainer
else
echo "❌ Portainer n'est pas en cours d'exécution"
echo "Derniers logs:"
docker logs --tail 20 portainer 2>/dev/null || echo "Aucun log disponible"
fi
echo
# Vérification réseau
echo "=== RÉSEAU ==="
echo "Ports en écoute:"
netstat -tlnp | grep -E "(9000|9443|9001)"
echo
echo "Connectivité externe:"
curl -s -o /dev/null -w "%{http_code}" http://localhost:9000 || echo "Erreur connexion HTTP"
curl -s -o /dev/null -w "%{http_code}" https://localhost:9443 -k || echo "Erreur connexion HTTPS"
echo
# Vérification ressources
echo "=== RESSOURCES ==="
echo "Utilisation disque:"
df -h | grep -E "(/$|/var)"
echo
echo "Utilisation mémoire:"
free -h
echo
echo "Charge système:"
uptime
echo
# Vérification volumes
echo "=== VOLUMES ==="
docker volume ls | grep portainer
echo
echo "Taille des volumes:"
docker system df -v | grep portainer
echo
echo "=== FIN DU DIAGNOSTIC ==="