Skip to main content

Gérer des images Docker Node.js dans GitHub Packages avec GitHub Actions

Écrit par
blog hero github actions docker push

13 juillet 2021

0 minutes de lecture

Si vous développez des logiciels open source aujourd’hui, il y a de fortes chances que vous soyez actif au sein de la communauté GitHub, en participant à des projets open source et à leurs dépôts. Un ajout récent à l’écosystème GitHub est GitHub Packages, annoncé en 2019 et qui bénéficie désormais de nouvelles mises à jour avec la disponibilité générale du registre de conteneurs GitHub Packages. Cela signifie que nous pouvons publier et récupérer des images basées sur Docker, ainsi que tout autre format compatible avec OCI, entièrement au sein de l’écosystème GitHub.

Dans cet article, je vais vous présenter pas à pas un workflow GitHub Actions. Vous apprendrez à publier des projets Node.js sous forme d’images Docker, puis à les envoyer vers le registre de conteneurs GitHub Packages.

Avant de commencer, saviez-vous qu’il existe un forum d’assistance dédié aux utilisateurs de GitHub, appelé GitHub Support Community ? N’hésitez pas à le consulter si vous avez besoin d’aide.

Le projet Node.js que nous utiliserons dans cet article est dockly, un outil en ligne de commande open source pour Node.js qui fournit une interface immersive dans le terminal pour gérer des conteneurs et des services Docker.

README de Dockly montrant une interface de terminal permettant de gérer des conteneurs Docker, avec des listes de conteneurs, des graphiques d’état et des journaux.

Créer un workflow GitHub Actions

Accédez à votre dépôt open source sur GitHub, cliquez sur l’onglet Actions, puis sur New Workflow et set up a workflow yourself. Vous devriez voir ceci :

Page GitHub Actions affichant le titre « Choisir un modèle de workflow » et des options pour sélectionner ou configurer un workflow

Commencez par définir le nom du fichier de workflow : docker-publish.yml, ou toute autre convention de nommage de votre choix.

GitHub peut préremplir le code du workflow. Si c’est le cas, supprimez-le et collez le code suivant :

name: Docker

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
  push:
    branches: [ main ]
    tags: [ 'v*.*.*' ]
  pull_request:
    branches: [ main ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

Le workflow ci-dessus définit les conventions suivantes :

  • Le workflow s’exécute uniquement lors des commits sur la branche main ou des pull requests vers la branche main. Remarque : Si votre dépôt utilise l’ancienne convention de branche master, remplacez son nom ici et dans le reste de l’extrait de code. Le workflow s’exécute également à chaque envoi de balises au dépôt au format semver <v*.*.*>, ce qui est pratique, car nous pouvons alors publier des images Docker pour chaque version.

  • Il garantit que la publication d’une nouvelle image Docker crée également des balises dans le dépôt GitHub.

  • Il définit des variables d’environnement globales pour les autres tâches du workflow, qui pointent vers GitHub Container Registry (ghcr.io), et définit le nom de l’image Docker selon les conventions habituelles de Docker Hub, comme <user>/<repo>, par exemple lirantal/nodejs-app.

Définissons ensuite nos tâches, qui mettront en place le processus de création de l’image Docker, puis de sa publication.

Créer une image Docker dans le cadre du workflow GitHub Actions

Pour publier des images Docker sur le registre de conteneurs GitHub Packages (ou même simplement sur GitHub), nous devons d’abord nous authentifier avec un compte valide. La première étape de la tâche de création et de publication consiste donc à se connecter.

Ajoutez le code suivant à la suite du code précédent :

jobs:
  build_and_publish:

    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract Docker metadata
        id: meta
        uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

Examinons les actions effectuées par les tâches décrites ici :

  1. La première étape consiste à extraire le code source du dépôt.

  2. Nous nous authentifions ensuite auprès du registre de conteneurs GitHub Packages. Comme vous pouvez le voir, nous réutilisons la variable d’environnement REGISTRY définie précédemment, qui pointe vers ghcr.io, le registre d’images de conteneurs de GitHub.

    Le nom d’utilisateur utilisé pour l’authentification est celui de la personne qui a lancé le workflow ; il doit correspondre à votre nom d’utilisateur en tant que propriétaire du dépôt. Le mot de passe utilise GITHUB_TOKEN, mis automatiquement à la disposition des workflows GitHub Actions. Vous n’avez pas besoin de l’ajouter manuellement comme secret ou variable d’environnement dans le dépôt. Notez que la connexion au registre n’a pas lieu pour une pull request : elle n’est de toute façon pas nécessaire et pourrait exposer des informations sensibles dans l’intégration continue des pull requests et des forks.

  3. La dernière étape de l’extrait de code ci-dessus extrait les métadonnées de l’image et les met à disposition du processus de création de l’image Docker (notre prochaine et dernière étape de ce workflow !). Ces métadonnées contiennent des informations sur les balises et les libellés, accessibles à l’action de création Docker. Plus précisément, l’entrée images définit l’image Docker à utiliser comme nom de base pour les balises.

Créer une image Docker et la publier dans le registre de conteneurs GitHub Packages

La dernière étape consiste à créer l’image Docker et à la publier. Il s’agit d’une étape unifiée qui utilise une action prenant en charge ces deux opérations. Notez toutefois que nous avons défini l’entrée push de ce workflow à l’aide d’une condition : la publication de l’image dans le registre n’est tentée que si l’événement n’est pas déclenché par une pull request :

      - name: Build and push Docker image
        uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
        with:
          context: .
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

Et voilà.

Une fois le workflow enregistré (en respectant l’indentation !) et déclenché en fusionnant ce workflow dans la branche main, il devrait créer une image et la publier dans le registre de conteneurs GitHub Packages.

Si tout s’est bien passé, vous devriez voir la coche verte tant attendue indiquant que la tâche a réussi, comme ici :

Workflow GitHub Actions montrant la réussite de la compilation et de l’envoi d’une image vers GHCR sur la branche master

Comment envoyer une image Docker vers le registre de conteneurs GitHub Packages ?

Utilisez l’action Docker officielle pour GitHub, docker/build-push-action, dans votre fichier de workflow GitHub Actions et assurez-vous qu’une variable d’environnement REGISTRY est définie sur ghcr.io.

Récupérer des images Docker depuis le registre de conteneurs GitHub Packages

Maintenant que notre projet a une image Docker publiée dans un registre public, testons-la en la récupérant depuis notre environnement de développement local :

$ docker pull ghcr.io/lirantal/my-nodejs-app
Using default tag: latest
latest: Pulling from lirantal/my-nodejs-app
b4d181a07f80: Pulling fs layer
de8ecf497b75: Pulling fs layer
69b92f9e5e70: Pulling fs layer
1f2b8e2c8ad8: Waiting
d0f4259cb643: Waiting
9ae47f3f99ba: Waiting
87270829eb60: Waiting
905fc634546c: Waiting

Comment préciser la version des images Docker à récupérer ?

La commande docker pull accepte un argument supplémentaire au format <registry>/<user>/<repo>:<image tag>. Par exemple, pour récupérer la balise d’image Docker « latest » du registre de conteneurs GitHub Packages pour l’image my-nodejs-app image, utilisez la commande suivante : docker pull ghcr.io/lirantal/my-nodejs-app

Hourra, ça marche !

Mais attendez… n’existe-t-il pas un moyen plus simple d’afficher les images Docker que j’envoie vers GitHub Packages ? Ne cherchez plus !

Trouver des images Docker dans GitHub Packages

Rendez-vous sur votre page de profil GitHub (par exemple la mienne : https://github.com/lirantal?tab=packages) pour voir toutes vos images Docker accessibles au public.

Si vous avez suivi ce tutoriel pour créer votre propre image Docker, pouvez-vous la retrouver ? Voici la page du paquet d’image Docker que j’ai envoyé vers GitHub Packages dans le cadre de l’intégration continue GitHub Actions du dépôt :

Page du registre de conteneurs GitHub pour dockly, affichant la commande Docker pull, les versions d’image étiquetées et le fichier README.

La balise latest est absente de l’image Docker publiée ?

Si vous avez essayé de récupérer l’image Docker par son nom, sans préciser la balise de l’image Docker pour la branche main ou master que vous utilisez, vous avez peut-être constaté que la balise Docker courante latest n’est pas disponible. Cela se produit si aucune balise semver (versionnement sémantique) n’a été envoyée. Vous en envoyez peut-être dans votre propre dépôt ; elles seront alors disponibles.

Pour imposer l’alias de balise Docker latest dans l’image publiée, nous pouvons mettre à jour l’action de métadonnées comme suit (remarquez la clé flavor supplémentaire sur plusieurs lignes) :

      - name: Extract Docker metadata
        id: meta
        uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          flavor: |
            latest=true
            prefix=
            suffix=

Notez toutefois que cela définira toujours une balise d’image latest comme alias de l’image Docker publiée lorsqu’un travail d’intégration continue est déclenché par la branche main.

Comment attribuer la balise latest à une image Docker ?

Pour baliser localement une image créée précédemment, nous pouvons utiliser la structure suivante de la commande Docker tag : docker tag <local image name> <new tag>. Par exemple : docker tag my-nodejs-app lirantal/my-nodejs-app:latest

Comment exécuter une image Docker avec un tag ?

Pour utiliser une balise d’image Docker spécifique lors de l’exécution d’une image, indiquez simplement le nom complet de l’image et sa balise dans la commande docker run. Par exemple : docker run --rm -p 27017:27017 mongo:latest

Intégrations pertinentes pour Docker et les conteneurs sur GitHub Actions Marketplace

Vous pouvez également trouver et créer des workflows GitHub Actions dans GitHub Actions Marketplace, qui propose plus de 9 000 workflows couvrant notamment la qualité du code, la gestion des dépendances et la sécurité. Vous y trouverez aussi les Snyk GitHub Actions, qui permettent de protéger vos projets contre les vulnérabilités de bibliothèques open source tierces et d’aider votre équipe à respecter les bonnes pratiques de codage sécurisé.

Pour créer, tester et publier des images Docker dans un registre, il existe un moyen plus simple que de parcourir la marketplace. Si votre dépôt contient déjà un fichier Dockerfile, GitHub le détectera automatiquement et vous proposera des workflows adaptés à GitHub Actions. Il vous suffit d’aller dans l’onglet Actions :

Page de configuration de GitHub Actions présentant des workflows Dockerfile recommandés pour publier un conteneur Docker ou créer une image Docker

Le premier workflow suggéré, Publish Docker Container, vous permettra de mettre en place un workflow similaire de création et de publication d’images Docker à celui que nous avons déjà examiné.

Résumé et ressources complémentaires

Cet article vous a donné envie d’adopter des pratiques de développement sécurisé ? Parfait ! Voici quelques ressources complémentaires pour vous lancer et marquer des points en matière de sécurité auprès de votre équipe :

  1. La sécurité de la chaîne d’approvisionnement est importante. Voici donc 10 bonnes pratiques de sécurité GitHub pour éviter de reproduire les erreurs courantes.

  2. Vous aimez Node.js et la création de paquets npm ? Moi aussi ! J’ai écrit un article pour vous aider à publier des paquets npm en toute sécurité avec GitHub Actions.

  3. Si vous passez beaucoup de temps dans l’écosystème GitHub, découvrez l’analyse de code de Snyk, qui s’intègre davantage à vos workflows : Analyse de code de sécurité GitHub : sécurisez vos dépendances open source

Lancez-vous dans les challenges Capture The Flag

Apprenez à résoudre des challenges Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.

Publié dans:

Lire la suite

Live Stream

Remediation Agent : pourquoi corriger vaut mieux que détecter

Découvrez comment le Remediation Agent de Snyk s’appuie sur des renseignements de sécurité, une analyse des risques de rupture et une validation pour transformer les vulnérabilités en demandes de fusion prêtes à être intégrées.

feature ai ide dark
Blog

Premier aperçu d’Evo Agentic AppSec : remédiation agentique et défense contre le code malveillant

Découvrez les premières capacités d’Agentic AppSec de Snyk : un Remediation Agent autonome qui corrige les vulnérabilités et une défense contre le code malveillant qui bloque les packages à risque avant leur mise en production.

feature insights context
Blog

Dans les coulisses de la compromission de keyv sur npm : malware preinstall, provenance fiable et hooks d’IDE

keyv 6.0.0 et dix versions npm associées ont diffusé un malware à l’installation. Découvrez les versions touchées, les empreintes, les étapes de détection et l’ordre de remédiation recommandé.