Introduction

Une image docker peut être vue comme une collection d'archive .tar.gz empilées l'une sur l'autre.

Nix est un gestionnaire de paquetages généraliste, capable de générer n'importe quel format. C'est donc sans surprise que l'on déniche pkgs.dockerTools qui contient de quoi générer des images docker.

Dans ce document, nous allons voir :

  • comment générer une image docker avec les binaires de notre choix
  • comment utiliser cette image dans une instance docker locale
  • comment téléverser l'image dans un repository distant, ici celui de plmlab
  • et finalement comment utiliser cette image docker dans un script d'intégration continue.

L'exemple que nous allons développer est celui du générateur statique de site zola

Générer une image

Nous allons construire une image contenant le binaire de zola.

Pour cela, dans le fichier nix/zola-docker.nix

{ pkgs ? import <nixpkgs> {} }:

pkgs.dockerTools.buildLayeredImage {
  name = "zola-docker";
  tag = "latest";
  contents = with pkgs; [              #1
    bash
    coreutils  # ls, mkdir, rm …
    gnugrep
    zola
  ];
}

#1 : you can add any package from https://search.nixos.org

Pour bâtir l'image, il faut appeler nix-build, qui par défaut va créer le résultat dans le répertoire ./result.

nix-build ./nix/zola-docker.nix 
# creates ./result, link to 
realpath ./result 
/nix/store/p5sf2bngqwvr45mq6jb8p6lppzgn5cym-zola.tar.gz 

L'image générée fait environ 24Mo.

Utiliser l'image générée dans l'instance docker locale

Comme tout .tar.gz contenant une image docker, il suffit d'utiliser docker load.

docker load -i $(realpath ./result)

Vous pouvez vérifier que votre nouvelle image est maintenant présente dans le registry local :

docker image ls | grep zola
zola-docker           latest  31b06badba31   53 years ago   70.5MB

Vous pouvez observer que la date de génération de l'image est l'epoch unix.

Test de l'image en local :

# -it : we need a tty
# --rm : remove container after end of exec
# zola-docker : image name to use
# /bin/bash : process to launch
docker run -it --rm zola-docker /bin/bash
## inside the container
bash-5.1# zola -V
zola 0.16.1
bash-5.1# bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
bash-5.1# grep --version
grep (GNU grep) 3.7
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others; see
<https://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.

Téléverser l'image sur le repository de plmlab

Plmlab est une instance de gitlab, qui fournit également la fonctionnalité de dépôt d'images de conteneurs docker (registry).

Pour téléverser une image dans un registry externe à partir de votre dépôt docker local, il faut :

  • pouvoir se connecter au dépôt distant : docker login
  • mettre un tag sur l'image avec le nom de l'image sur le dépôt distant
  • utiliser docker push pour transférer l'image du dépôt local au dépôt distant

Se connecter à un registry externe

Il faut générer un token à partir de votre profil sur plmlab, en lui donnant les droits de lecture et d'écriture.

Définissez ensuite les variables d'environnement suivantes :

# generate a personal token with read and write registrya access
# from https://plmlab.math.cnrs.fr/-/profile/personal_access_tokens
PRIV_REGISTRY_USER=your-plmlab-id                       ## <= INSERT YOURS !!
PRIV_REGISTRY_PASSWORD="glpat-xyzyxzyxzyxzyxzyxzyxzyzx" ## <= INSERT YOURS !!
PRIV_REGISTRY=registry.plmlab.math.cnrs.fr

Vous pouvez ensuite vous connecter au registry de plmlab :

docker login ${PRIV_REGISTRY} -u ${PRIV_REGISTRY_USER} -p ${PRIV_REGISTRY_PASSWORD}

Cela crée ou complète le fichier ~/.docker/config.json :

{
    "auths": {
        "registry.plmlab.math.cnrs.fr": {
            "auth": "AbCAbCAbCAbCAbCAbCAbCAbCAbCAbCAbCAbCAbCAbCAbC="
        }
    }
}

Mettre un tag sur l'image

Il faut ajouter un tag indiquant l'endroit où stocker l'image dans le registry distant.

PRIV_REGISTRY=registry.plmlab.math.cnrs.fr
GITLAB_PROJECT=plmteam/docs/zola-doc
docker tag zola-docker:latest $PRIV_REGISTRY/${GITLAB_PROJECT}/zola-docker 
docker login $PRIV_REGISTRY

Vous pouvez observer le nouveau tag sur votre image dans le registry local :

docker image ls | grep zola
zola-docker        latest     31b06badba31   53 years ago   66.9MB
registry.plmlab.math.cnrs.fr/plmteam/docs/zola-doc/zola-docker  \
                   latest     31b06badba31   53 years ago   66.9MB

Pousser l'image

# can only push to projet, not group
PRIV_REGISTRY=registry.plmlab.math.cnrs.fr
GITLAB_PROJECT=plmteam/docs/zola-doc

docker push $PRIV_REGISTRY/$GITLAB_PROJECT/zola-docker

Vous pouvez vous rendre sur ${PRIV_REGISTRY}/${GITLAB_PROJECT}/container_registry pour observer l'apparition de l'image dans l'interface web de gitlab.

On pousse l'image dans la partie container registry du projet dans lequel on veut l'utiliser pendant l'intégration continue.

Utiliser cette image dans un processus d'intégration continue.

Dans le .gitlab-ci.yml de votre projet, il faut référéncer l'image du projet courant :

---
image: "${CI_REGISTRY_IMAGE}/zola-docker"


# mandatory : the zola theme is in a submodule
variables:
  GIT_SUBMODULE_STRATEGY: recursive

test:
  script:
    - ./publish private
  except:
    variables:
      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

pages:
  script:
    - ./publish private
  artifacts:
    paths:
      - public
  only:
    variables:
      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  environment: production