Aller au contenu

Création d'une image Docker

Commençons avec un programme simple

Pour illustrer ce chapitre, commençons par un programme en Go qui affiche un message de bienvenue, ainsi que quelques informations sur votre système.

Créez un nouveau dossier et ajoutez-y ces deux fichiers “go.mod” et “hello-devops.go” :

go.mod
module hello-devops

go 1.25.0
hello-devops.go
package main

import (
        "fmt"
        "runtime"
)

func main() {
        fmt.Println("Hello DevOps!")
        fmt.Println("Go version:", runtime.Version())
        fmt.Println("Architecture:", runtime.GOARCH)
        fmt.Println("OS:", runtime.GOOS)
}

Pour vérifier que tout fonctionne correctement, vous pouvez compiler ces programmes sur votre machine. Si ce n’est pas encore fait, téléchargez l’environnement de développement Go et installez-le sur votre machine.

Tapez maintenant la commande suivante dans un terminal :

go run .

et vous devriez obtenir quelque chose qui ressemble à ça :

Hello DevOps!
Go version: go1.25.0
Architecture: amd64 (ou arm64)
OS: windows (ou linux, ou darwin)

Bravo! Vous avez écrit un programme en Go!

Conteneurisation du programme

Mais si vous n’aviez pas envie (ou si vous ne pouviez pas) installer l’environnement de développement Go, vous auriez aussi pu exécuter ce programme en passant par une image Docker. C’est ce que nous allons faire maintenant.

Créez un fichier “Dockerfile” dans le même dossier :

Dockerfile
FROM golang:1.25 AS builder
WORKDIR /app
COPY go.mod hello-devops.go ./
RUN go build .

FROM alpine:3.23
WORKDIR /root/
COPY --from=builder /app/hello-devops /usr/local/bin/hello-devops
CMD ["/usr/local/bin/hello-devops"]

Attention

Dans le Dockerfile ci-dessus, nous téléchargeons les images du “registry” DockerHub. Pour des téléchargements anonymes, Dockerhub impose une limite de 10 téléchargements par adresse IP et par heure! Si vous bloquez votre propre adresse IP, vous ne pourrez plus télécharger d’images Docker depuis DockerHub, mais les dégâts ne toucheront que votre propre adresse IP. Par contre, si vous bloquez l’adresse IP des serveurs de l’école, vous bloquerez tout le monde pendant une heure!

Pour s’adapter à la limite imposée par DockerHub, nous commençons par créer un compte sur DockerHub. Rendez-vous sur DockerHub et créez un compte. Si le site vous demande de choisir entre un compte Work ou Personal, choisissez Personal.

Création d'un compte DockerHub

Dès que vous avez créé votre compte, vous pouvez vous authentifier avec la commande suivante:

docker login

Suivez les instructions et vous devriez voir un message du genre :

Login Succeeded

Losque vous êtes authentifié, vous avez droit à 40 téléchargements par heure (et par utilisateur).

Note

Une autre manière de contourner la limite imposée par Dockerhub consiste à simplement utiliser un autre “registry” comme le Public Elastic Container Registry d’Amazone.

Note

Les “runners” de l’école utilisent un cache pour les images Docker provenant de DockerHub, mais lorsque nous utilisons Docker à l’intérieur de Docker, le cache n’est pas utilisé

construisez maintenant une image Docker :

docker build -t hello-devops .

et exécutez-la :

docker run --rm hello-devops

Vous obtenez quelque chose comme ça :

Hello DevOps!
Go version: go1.25.0
Architecture: arm64
OS: linux

l’architecture est la même que votre machine (amd64 ou arm64), mais l’OS est maintenant “linux”, car le container fonctionne bien dans un environnement Linux.

Utilisation du CI/CD

Jusqu’ici, nous avons fait toutes les opérations sur notre ordinateur personnel. Il est temps de passer au CI/CD et laisser les ordinateurs du cloud faire le travail.

Ajoutez le fichier “.gitlab-ci.yml” à votre dossier :

.gitlab-ci.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
build-docker-image:
  image:
    name: moby/buildkit:rootless
    entrypoint: [""]
  stage: build
  variables:
    BUILDKITD_FLAGS: --oci-worker-no-process-sandbox
    DOCKER_CONFIG: "$CI_PROJECT_DIR/.docker"
    CACHE_IMAGE: $CI_REGISTRY_IMAGE:cache
    IMAGE_TAG_SHA: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
  before_script:
    - mkdir -p "$DOCKER_CONFIG"
    - |
      echo "{
        \"auths\": {
          \"${CI_REGISTRY}\": {
            \"auth\": \"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"
          },
          \"https://index.docker.io/v1/\": {
            \"auth\": \"$(printf "%s:%s" "${DOCKER_HUB_USER}" "${DOCKER_HUB_PASSWORD}" | base64 | tr -d '\n')\"
          }
        }
      }" > "$DOCKER_CONFIG/config.json"
  script:
    - |
      # Use git tag if available, otherwise use branch name (preserves dots in tags)
      TAG_NAME=${CI_COMMIT_TAG:-$CI_COMMIT_REF_NAME}
      buildctl-daemonless.sh build \
        --frontend dockerfile.v0 \
        --local context=. \
        --local dockerfile=. \
        --export-cache type=registry,ref=$CACHE_IMAGE \
        --import-cache type=registry,ref=$CACHE_IMAGE \
        --output type=image,\"name=$IMAGE_TAG_SHA,$IMAGE_TAG_LATEST,$CI_REGISTRY_IMAGE:$TAG_NAME\",push=true

Note

La création d’image Docker à l’intérieur d’un container Docker est un processus un peu compliqué, et le fichier .gitlab-ci.yml ci-dessus décrit la manière recommandée de le faire dans GitLab CI/CD. Il existe cependant d’autres méthodes, comme l’utilisation de “Docker in Docker” (DinD), de “Buildah” ou de “Kaniko”, mais la méthode décrite ci-dessus est plus rapide et plus facile à mettre en place.

Avec ce fichier, vous indiquez à GitLab qu’il doit construire une image Docker à chaque fois qu’une nouvelle version est poussée (push) dans le dépôt. L’image Docker construite est ensuite publiée dans le “registry” de GitLab, et vous pourrez la télécharger et l’exécuter sur votre machine.

Si ce n’est pas déjà fait, créez un dépôt dans le GitLab de l’école et mettez-y tous les fichiers que vous venez de créer.

Afin d’utiliser votre compte DockerHub dans le CI/CD, vous devez encore obtenir un token pour DockerHub. Connectez-vous à votre compte sur DockerHub et cliquez sur votre login name en haut à droite, puis sur Account Settings

Dans la section Personal access tokens, créez un nouvel Access Token avec le scope “Read, Write, Delete”.

Note

Si vous souhaitez uniquement lire les images publiques, vous pouvez choisir le scope “Public Repo Read-only”, mais plus tard nous allons publier notre image dans DockerHub et pour cela, nous avons besoin du scope “Read, Write, Delete”. Je vous recommande donc de choisir ce scope dès le début, mais d’un point de vue de la sécurité, il est préférable de choisir le scope le plus bas possible.

A la ligne 21 du fichier .gitlab-ci.yml, ci-dessus, les deux variables d’environnement $DOCKER_HUB_USER et $DOCKER_HUB_TOKEN. doivent contenir le user name et l’Access Token que vous venez de créer. Définissez ces variables dans votre projet GitLab :

Allez dans “Settings” → “CI/CD” → “Variables” et ajoutez ces deux variables. Pour plus de sécurité, protégez le contenu de ces variables en cochant la case Masked and hidden. Notez que pour $DOCKER_HUB_USER, vous pouvez vous contenter de protéger cette variable avec l’option Masked.

Après avoir synchronisé votre dépôt (avec git push), vous devriez voir une nouvelle entrée dans la section “CI/CD” → “Pipelines” :

Vous devriez aussi avoir une entrée dans “Deploy” → “Container registry”.

Vous pouvez télécharger et exécuter cette image avec la commande :

docker run --rm registry.forge.hefr.ch/<NAMESPACE>/<REPOSITORY>:latest

Info

Si votre projet est privé, vous devrez probablement vous authentifier avant de pouvoir utiliser l’image :

docker login registry.forge.hefr.ch

et vous devriez obtenir ceci :

Hello DevOps!
Go version: go1.25.0
Architecture: amd64
OS: linux

L’architecture sera toujours amd64 car le runner qui a compilé votre programme dans GitLab est une machine avec une architecture amd64 et si vous faites tourner cette image sur un Mac récent (avec une puce ARM), vous observerez le message suivant:

WARNING: The requested image's platform (linux/amd64) does not match
the detected host platform (linux/arm64/v8) and no specific platform
was requested

Note

Notez l’utilisation du tag cache dans le fichier .gitlab-ci.yml. Ce tag permet d’améliorer les performances du processus de construction de l’image Docker en utilisant un cache partagé entre les différentes exécutions du pipeline.

De manière générale, l’utilisation d’un cache est une bonne pratique pour améliorer les performances du CI/CD. Lisez la documentation de GitLab sur le cache pour en savoir plus sur les différentes options disponibles.