À la une · Fiche technique
Comment déployer une image Docker depuis GitHub Actions ?
Apprenez à construire, taguer et déployer une image Docker automatiquement avec GitHub Actions. Connexion au registry, docker/build-push-action, push sur Docker Hub ou GHCR et déploiement sur votre serveur. Le pont entre Docker et la CI/CD.
Voici une fiche que j’attendais d’écrire depuis un moment parce qu’elle fait le lien entre deux séries de NX. Docker d’un côté les CI/CD avec GitHub Actions de l’autre.
Jusqu’ici, vous avez appris à construire une image Docker et à déclencher un workflow GitHub Actions. Aujourd’hui, on assemble les deux ! Autrement dit, comment faire pour qu’à chaque push, GitHub Actions construise votre image Docker et la déploie automatiquement ?
C’est exactement ce qui transforme un projet « qui marche sur ma machine » en une vraie application livrée en continu. On y va.
La grande idée : build → push → deploy
Avant le code, posons le schéma mental. Déployer une image Docker depuis un workflow, ça se résume presque toujours à trois étapes :
- Build → GitHub Actions construit l’image à partir de votre
Dockerfile; - Push → l’image est envoyée sur un registry (Docker Hub, GHCR…) ;
- Deploy → votre serveur récupère cette image et lance le conteneur.
Si la notion de registry est floue, je vous renvoie à la fiche Qu’est-ce qu’un registry Docker ?. C’est le maillon central de toute cette chaîne. Le registry, c’est l’entrepôt d’où partent et où arrivent vos images.
On va dérouler ces trois étapes une par une.
Étape 1 - Se connecter au registry
Impossible de pousser une image sans s’authentifier auprès du registry. Pour ça,
GitHub met à disposition l’action officielle
docker/login-action.
Voici la connexion à Docker Hub :
- name: Connexion à Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
Vous remarquez le ${{ secrets.DOCKERHUB_TOKEN }} ? On ne met JAMAIS un mot
de passe en clair dans un workflow. On passe par les secrets GitHub. Si vous
ne savez pas encore comment ça marche, gardez cette fiche sous le coude :
Comment gérer les secrets dans GitHub Actions ?.
On s’en sert dès maintenant.
Étape 2 - Construire et pousser l’image
Une fois connecté, on enchaîne avec
docker/build-push-action, qui
fait le build et le push en une seule étape.
- name: Build et push de l'image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: moncompte/mon-api:latest
Décryptage :
context: .→ le dossier qui contient votreDockerfile;push: true→ une fois l’image construite, on l’envoie sur le registry ;tags:→ le nom et le tag de l’image publiée.
Un conseil au passage. Évitez de tout taguer en latest. C’est pratique
mais on ne sait plus quelle version tourne réellement. Préférez taguer avec le
SHA du commit, comme pour les artefacts :
tags: moncompte/mon-api:${{ github.sha }}
Le workflow complet (build + push)
Mettons les deux étapes bout à bout dans un workflow déclenché à chaque push sur
main :
name: Build & Push Docker image
on:
push:
branches: [main]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout du code
uses: actions/checkout@v4
- name: Connexion à Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build et push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: moncompte/mon-api:${{ github.sha }}
À ce stade, à chaque push sur main, votre image fraîchement construite se
retrouve sur Docker Hub. Il ne reste plus qu’à la déployer.
Étape 3 - Déployer l’image sur votre serveur
Le push, c’est bien, mais votre serveur ne va pas deviner qu’une nouvelle image est disponible. Il faut lui dire d’aller la chercher et de relancer le conteneur.
L’approche la plus simple et la plus répandue : se connecter en SSH au serveur
depuis le workflow, puis lancer un docker pull suivi d’un docker run. On
utilise pour ça l’action
appleboy/ssh-action :
- name: Déploiement sur le serveur
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
docker pull moncompte/mon-api:latest
docker stop mon-api || true
docker rm mon-api || true
docker run -d --name mon-api -p 3000:3000 moncompte/mon-api:latest
Là encore, tout ce qui est sensible (l’adresse du serveur, l’utilisateur, la clé SSH) passe par des secrets. On ne met rien en dur.
Le || true après docker stop et docker rm est un petit réflexe utile. Au
tout premier déploiement, le conteneur n’existe pas encore, et sans ça le
workflow échouerait bêtement.
Bonnes pratiques
Quelques réflexes pour un déploiement propre :
- Taguez avec le SHA du commit (
${{ github.sha }}) pour savoir exactement quelle version tourne, et gardez éventuellement unlatesten parallèle. - Optimisez votre image avant de la déployer : une image légère se pousse et se récupère plus vite. Voir Comment optimiser une image Docker ? et Comment faire un multi-stage build ?.
- Utilisez le cache de build de
build-push-actionpour ne pas tout reconstruire à chaque fois (on en reparlera dans la fiche sur l’optimisation des workflows). - Séparez build et déploiement en deux jobs si vous voulez, par exemple, ne déployer que si les tests passent.
Bonus - Docker Hub ou GHCR ?
Vous n’êtes pas obligé de passer par Docker Hub. GitHub propose son propre
registry, GHCR (ghcr.io), directement intégré à vos dépôts.
Son gros avantage : pas besoin de créer un token à part, vous pouvez utiliser le
GITHUB_TOKEN fourni automatiquement à chaque workflow :
- name: Connexion à GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
Pensez juste à donner la permission packages: write à votre job :
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
Mon conseil : si votre code est déjà sur GitHub, GHCR est souvent le choix le plus simple (tout reste au même endroit).
Et voilà, vous savez maintenant construire et déployer une image Docker en continu depuis GitHub Actions ! Pour résumer : on build l’image, on la pousse sur un registry, et le serveur va la chercher pour relancer le conteneur — le tout automatiquement à chaque push.
C’est vraiment le moment où Docker et la CI/CD se rejoignent. D’ici là, je vous invite :
- à sécuriser tout ça avec la fiche Comment gérer les secrets dans GitHub Actions ? ;
- à (re)découvrir le cours sur les pipelines CI/CD et le cours sur Docker.
Ressources
Codez bien, Thomas
NX Academy


