## Introduction

Docker Hub est bien plus qu'un simple espace de stockage d'images. C'est un élément central de nombreux pipelines CI/CD, et bien l'utiliser implique de comprendre ses capacités avancées. Cet article couvre les concepts essentiels en production : la signature d'images avec Docker Content Trust, l'automatisation pilotée par webhooks, la gestion des limites de débit, la conception des dépôts et les contrôles de sécurité. Chaque section inclut des commandes concrètes et les résultats attendus pour que vous puissiez appliquer immédiatement ces idées.

L'objectif est la sécurité opérationnelle. Avant d'effectuer des changements, observez l'état actuel, limitez le rayon d'impact, utilisez des espaces réservés plutôt que des secrets, vérifiez le résultat et documentez les étapes de récupération. Ce guide s'adresse aux développeurs, ingénieurs DevOps et responsables techniques qui gèrent Docker Hub en équipe ou en environnement de production.

## Inventaire de version et d'environnement

Commencez par identifier votre environnement de travail. Connaître la version de Docker, le système d'exploitation et la méthode d'accès à Docker Hub (CLI, API ou interface web) évite de perdre du temps. Exécutez ces commandes sur votre poste de travail ou votre runner CI :

```bash
docker version --format '{{.Server.Version}}'
docker info --format '{{.OperatingSystem}}'
```

Résultat attendu :

```text
24.0.7
Ubuntu 22.04.3 LTS
```

Si vous utilisez Docker Desktop, vérifiez que Kubernetes ne consomme pas les ressources nécessaires aux tests de registre local. Sur macOS, exécutez `docker system df` pour voir l'utilisation du disque avant de tirer de grandes images.

Avant de toucher à Docker Hub, confirmez les éléments de base :

- Vous êtes connecté : `docker login`
- Votre compte fonctionne : `docker pull hello-world`
- Votre réseau autorise le HTTPS sortant sur le port 443 vers `registry-1.docker.io` et `auth.docker.io`

Si `docker pull` échoue avec une erreur TLS, vérifiez l'horloge système. Docker Hub exige une heure précise pour la validation des certificats :

```bash
date
```

Une horloge décalée de plus de quelques minutes provoque `x509: certificate has expired or is not yet valid`. Corrigez avec une synchronisation NTP avant de déboguer autre chose.

Pour les environnements CI, stockez les identifiants dans un gestionnaire de secrets. Ne codez jamais en dur un mot de passe Docker Hub dans un fichier de pipeline. La section suivante présente des modèles de configuration sécurisés.

## Chemin de configuration sécurisé

Les erreurs de configuration sont parmi les incidents Docker Hub les plus courants. Un chemin sécurisé signifie changer une chose à la fois et savoir comment revenir en arrière. Par exemple, si vous ajoutez une étiquette de build multi-architecture, vérifiez d'abord la liste des manifestes :

```bash
docker buildx imagetools inspect myuser/myapp:1.0
```

Résultat attendu :

```text
Name:      docker.io/myuser/myapp:1.0
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:8a1c...

Manifests:
  Name:      docker.io/myuser/myapp:1.0@sha256:aaaa...
  Platform:  linux/amd64
  Name:      docker.io/myuser/myapp:1.0@sha256:bbbb...
  Platform:  linux/arm64
```

Si vous ne voyez qu'une seule plateforme, votre builder n'est pas correctement configuré. Ne poussez pas l'étiquette tant que les deux plateformes n'apparaissent pas.

Un autre domaine qui bénéficie d'un chemin sécurisé est l'injection de variables d'environnement. Un modèle courant consiste à passer des arguments de build pour l'étiquetage :

```bash
docker build --build-arg VERSION=1.2.3 -t myuser/myapp:1.2.3 .
```

Dans le Dockerfile, utilisez :

```Dockerfile
ARG VERSION
LABEL org.opencontainers.image.version=$VERSION
```

Cela évite les fautes de frappe dans les étiquettes. Pour les valeurs sensibles comme les jetons d'API, n'utilisez jamais d'arguments de build. Ils sont visibles dans l'historique de l'image (`docker history myuser/myapp:1.2.3`). Utilisez plutôt les secrets Docker ou des variables d'environnement au moment de l'exécution :

```bash
docker run -e API_TOKEN=$(cat /run/secrets/api_token) myuser/myapp:1.2.3
```

Lors du montage de fichiers de configuration, testez avec un montage local avant de passer à un volume nommé :

```bash
docker run -v $(pwd)/config:/app/config myuser/myapp:1.2.3
```

Après avoir confirmé que l'application lit le fichier, passez à un volume nommé pour un comportement similaire à la production :

```bash
docker volume create app_config
docker run -v app_config:/app/config myuser/myapp:1.2.3
```

Un test de redémarrage est obligatoire. Arrêtez le conteneur, recréez-le et vérifiez la persistance des données :

```bash
docker stop myapp && docker rm myapp
docker run -d --name myapp -v app_config:/app/config myuser/myapp:1.2.3
docker exec myapp cat /app/config/settings.json
```

Si le fichier est absent, le conteneur a écrit dans sa couche inscriptible, pas dans le volume. Corrigez l'instruction `VOLUME` du Dockerfile ou la commande de montage.

## Vérification et diagnostics

Après tout changement, vérifiez le résultat avec une commande en lecture seule avant de déclarer le succès. Pour les poussées d'images, vérifiez le dépôt sur Docker Hub via l'API :

```bash
curl -s "https://hub.docker.com/v2/repositories/myuser/myapp/tags/1.2.3" | jq .
```

Résultat attendu :

```json
{
  "name": "1.2.3",
  "tag_status": "active",
  "last_updated": "2024-11-03T14:22:31.000000Z",
  "images": [
    {
      "architecture": "amd64",
      "digest": "sha256:aaaa...",
      "size": 184729600
    }
  ]
}
```

Si `tag_status` n'est pas `active`, l'étiquette a peut-être été supprimée ou une poussée est encore en cours. Attendez quelques secondes et réessayez.

Un diagnostic utile pour les limites de débit consiste à inspecter les en-têtes de réponse après un pull :

```bash
docker pull alpine:latest -q
docker pull alpine:latest 2>&1 | grep -i rate
```

Mais les en-têtes de réponse ne sont pas affichés par le CLI Docker. Utilisez plutôt l'API directement :

```bash
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/alpine:pull" | jq -r .token)
curl -I -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/library/alpine/manifests/latest
```

Recherchez des en-têtes comme :

```text
RateLimit-Limit: 100;w=21600
RateLimit-Remaining: 98
```

Cela indique la fenêtre de limite (21600 secondes = 6 heures) et le nombre de pulls restants. Si `RateLimit-Remaining` est proche de zéro, passez à un compte authentifié ou à un miroir.

Pour le diagnostic des webhooks, inspectez les livraisons récentes :

```bash
curl -s "https://hub.docker.com/v2/webhooks/myuser/myapp/" | jq .
```

Si vous ne voyez pas votre webhook, il a peut-être été créé dans un autre compte ou dépôt. Les webhooks sont spécifiques à chaque dépôt, pas globaux.

## Modes de défaillance et récupération

Les échecs courants incluent les erreurs d'authentification, l'épuisement des limites de débit et les problèmes de livraison des webhooks. Voici comment diagnostiquer et récupérer de chacun.

### Erreurs d'authentification

Si `docker login` échoue avec `Error response from daemon: Get "https://registry-1.docker.io/v2/": unauthorized`, vérifiez vos identifiants. Utilisez un jeton d'accès personnel (PAT, Personal Access Token) au lieu d'un mot de passe. Docker Hub a déprécié les mots de passe pour l'accès API. Créez un PAT dans l'interface web de Docker Hub sous Paramètres du compte > Sécurité > Nouveau jeton d'accès. Ensuite, connectez-vous :

```bash
docker login -u myuser --password-stdin < my-pat.txt
```

Ne mettez jamais le PAT dans un argument de ligne de commande. Utilisez stdin ou un fichier secret.

Si vous voyez `denied: requested access to the resource is denied`, le jeton n'a peut-être pas les portées nécessaires pour le dépôt. Vérifiez les permissions du PAT. Pour l'accès en écriture, le PAT a besoin de la portée `Read & Write` sur le dépôt.

### Limites de débit

Docker Hub applique des limites de débit de pull : les utilisateurs anonymes ont 100 pulls par 6 heures par adresse IP ; les utilisateurs authentifiés gratuits ont 200 pulls par 6 heures ; les forfaits payants ont des limites plus élevées. Si vos tâches CI atteignent la limite, les builds échouent avec `toomanyrequests: You have reached your pull rate limit`.

Options de récupération :

1. Authentifiez tous les pulls à l'aide d'un compte Docker Hub ou d'un PAT. Même les comptes authentifiés gratuits bénéficient du double de la limite anonyme.
2. Utilisez un miroir de registre local ou un cache pass-through. Configurez le démon Docker avec `registry-mirrors` :

```json
{
  "registry-mirrors": ["https://mirror.example.com"]
}
```

Redémarrez Docker après ce changement.
3. Réduisez les pulls inutiles en mettant en cache les images de base dans la CI. La plupart des plateformes CI offrent la mise en cache des couches Docker. Dans GitHub Actions, utilisez `docker/build-push-action` avec `cache-from` et `cache-to`.

### Échecs de livraison des webhooks

Si un webhook reçoit des événements mais que votre endpoint renvoie des erreurs, le système de webhooks réessaie pendant 24 heures avec un backoff exponentiel. Vérifiez le code de réponse renvoyé par votre serveur. Renvoyer 200 indique un succès. Renvoyer 4xx ou 5xx déclenche des réessais. Pour éviter les événements en double, rendez votre gestionnaire idempotent. Par exemple, si un événement push déclenche un déploiement, incluez le condensé du push dans l'identifiant du déploiement. Les événements en double avec le même condensé sont ignorés.

Si les webhooks cessent de se déclencher, vérifiez les paramètres du dépôt. Un webhook avec un secret expiré ou une URL invalide est silencieusement désactivé par Docker Hub après des échecs répétés.

Le chemin de récupération pour la plupart des problèmes est : vérifiez les journaux (`docker logs`, journaux CI ou journaux de livraison des webhooks), vérifiez les paramètres actuels via l'API, puis effectuez un seul changement à la fois.

## Pièges courants et comment les éviter

Plusieurs pièges reviennent régulièrement dans l'utilisation de Docker Hub :

### 1. Étiqueter les images comme `latest` en production

`latest` est une étiquette par défaut sans signification sémantique. Elle pointe souvent vers la build la plus récente, pas vers une version stable. Si vous tirez `latest` en production, vous risquez d'obtenir des changements non testés.

Comment éviter : Utilisez des étiquettes de version sémantique (`1.2.3`) et des condensés immuables. Par exemple, déployez avec `myuser/myapp@sha256:8a1c...` au lieu de `myuser/myapp:latest`. Le condensé fige le contenu exact de l'image.

### 2. Stocker des secrets dans les images

Même après avoir supprimé une couche, des secrets peuvent rester dans l'historique de l'image ou les caches distants. Une erreur courante consiste à copier un fichier `.env` avec des identifiants dans le contexte de build, puis exécuter `COPY . .`.

Comment éviter : Utilisez un fichier `.dockerignore` pour exclure les fichiers sensibles. Ajoutez des motifs :

```text
.env
*.pem
id_rsa
```

Pour les secrets au moment de l'exécution, utilisez les secrets Docker ou des variables d'environnement passées au lancement.

### 3. Ignorer les besoins multi-architecture

Si votre équipe développe sur Apple Silicon mais déploie sur des serveurs x86_64, les images mono-architecture provoquent `exec format error` sur les hôtes incompatibles.

Comment éviter : Utilisez `docker buildx` pour créer des images multi-architectures :

```bash
docker buildx build --platform linux/amd64,linux/arm64 -t myuser/myapp:1.2.3 --push .
```

Vérifiez que la liste des manifestes inclut les deux plateformes avant le déploiement.

### 4. Ne pas surveiller l'accès aux dépôts

Sans journaux d'audit, il est difficile de savoir qui a tiré ou poussé une image. Docker Hub fournit des journaux d'accès pour les forfaits Team et Business. Examinez-les régulièrement pour détecter les accès non autorisés.

Comment éviter : Attribuez les permissions des dépôts selon le principe du moindre privilège. Chaque membre de l'équipe ne doit avoir que l'accès nécessaire à son rôle.

### 5. Négliger la validation de la charge utile des webhooks

Les charges utiles des webhooks incluent une signature dans l'en-tête `X-Hub-Signature`. Si vous ne vérifiez pas la signature, un attaquant pourrait envoyer de faux événements à votre endpoint.

Comment éviter : Implémentez une validation HMAC (Hash-based Message Authentication Code). À l'aide du secret du webhook, calculez le HMAC SHA256 du corps de la requête et comparez-le à la valeur de l'en-tête. Une non-correspondance signifie qu'il faut rejeter l'événement.

## Liste de contrôle des opérations

Utilisez cette liste de contrôle avant et après toute opération Docker Hub. Elle est rédigée pour un responsable d'équipe qui possède le processus, et le statut est examiné chaque semaine lors d'une réunion debout.

- **Propriétaire :** Priya Shah, responsable ingénierie
- **Cadence d'examen :** Hebdomadaire, chaque lundi matin

| # | Élément de la liste de contrôle | Commande / Action de vérification | Résultat attendu | Propriétaire |
|---|---|---|---|---|
| 1 | Connexion à Docker Hub | `docker login` | Connexion réussie | Priya Shah |
| 2 | Confirmer l'état actuel du dépôt | `curl -s https://hub.docker.com/v2/repositories/myuser/myapp/tags | jq '.results[].name'` | Étiquettes attendues présentes | Priya Shah |
| 3 | Vérifier que le scan de vulnérabilités de l'image est réussi | Consulter la page des scans Docker Hub ou `docker scout cves myuser/myapp:1.2.3` | Aucune CVE critique ou élevée | Membre de l'équipe DevSecOps, rotation hebdomadaire |
| 4 | Le endpoint du webhook renvoie 200 pour un événement de test | Envoyer un événement de test depuis les paramètres du webhook | Code de réponse 200 observé | Priya Shah |
| 5 | Limite de débit restante au-dessus du seuil | `curl -I ...` et vérifier l'en-tête `RateLimit-Remaining` | Restant > 50 | Administrateur CI, rotation |
| 6 | Sauvegarde des métadonnées du dépôt privé | Utiliser `docker pull` pour toutes les étiquettes du dépôt privé vers un registre local | Toutes les étiquettes stockées localement | Priya Shah |
| 7 | Examen des journaux d'accès | Examiner les journaux d'accès Docker Hub des 7 derniers jours | Aucune IP ou utilisateur inattendu | Responsable sécurité, Alex Chen |

Exécutez la commande de vérification de la colonne 3 pour chaque élément. Si un résultat attendu échoue, ne poursuivez pas l'opération. Documentez l'échec, attribuez une correction et réexécutez la liste de contrôle avant l'examen hebdomadaire.

Un petit test local similaire à la production est inclus dans la liste de contrôle pour le déploiement de nouvelles étiquettes : tirez l'image sur un hôte de préproduction, exécutez un test de fumée et comparez le condensé avec la build. Seulement si ces étapes réussissent, procédez à la promotion en production.

## Conclusion

Les concepts avancés de Docker Hub sont des outils pratiques, pas une théorie abstraite. En comprenant le versionnage, la signature d'images, les webhooks, les limites de débit et la sécurité, vous pouvez exploiter Docker Hub en toute confiance. La clé est d'observer avant de changer, de limiter le rayon d'impact, de vérifier avec des commandes concrètes et de documenter la récupération. Utilisez la liste de contrôle de cet article comme point de départ, adaptez-la à votre équipe et examinez-la chaque semaine. Lorsque quelque chose tourne mal, les commandes de diagnostic et les modes de défaillance couverts ici vous remettront rapidement sur la bonne voie.

Comme prochaine étape, choisissez une vérification à faible risque, comme vérifier votre statut de limite de débit ou valider une signature de webhook, et exécutez-la aujourd'hui. Enregistrez le résultat et comparez-le au résultat attendu. Cette petite action construit les habitudes qui préviennent les incidents plus importants plus tard.