Déploiement continu (avancé)
Il y a plusieurs possibilités qui dépendent aussi de vos objectifs vis à vis du déploiement, et les critères peuvent être nombreux :
- simplicité d’usage : image déjà packagé par une équipe ou distributio nue ?
- rapidité du déploiement : compilation des sources ou binaires ?
- reproductibilité : Ubuntu LTS ou Debian Unstable ?
- taille de l’image ?
- etc :
Dans la partie CI/CD nous avons vu la version simple, rapide, efficace, presque … magique.
Toutefois, pour des raisons diverses et variées vous pouvez être amené(e)s un jour à déployer vos propres recettes de CI/CD pour des Notebooks.
Voici quelques pistes de recettes supplémentaires.
From Scratch, ou presque…
Pour garder les mains libre (pas de RStudio, de Posit intégré à l’image par exemple), et avoir le maximum de liberté et de flexibilité, alors il est possible de partir d’une image de distribution nue.
Toutes les recettes Dockerfile
sont ici si vous voulez vous en inspirer : https://github.com/rocker-org/rocker-versioned2/tree/master/dockerfiles
Si vous vous sentez concerné par la reproductibilité future de votre workflow, alors une Debian est tout indiqué, ne serait ce que pour les efforts réalisés par l’équipe ces dernières années au sein du consortium Reproducible Builds
Il est possible de partir d’une image Debian et d’installer au dessus la version de R qui vous convient. Vous trouverez de la documentation sur le CRAN à ce sujet.
Il faudra, au moins la première fois, s’armer de patience car la compilation des packages R peut être longue. Seules les fonctionnalités de cache propre au CI vous permettront de gagner du temps.
image: debian:bookworm-20250610-slim
variables:
QUARTO_VERSION: 1.8.2
before_script:
- export LC_ALL=C.UTF-8
- apt-get update && apt-get install -y apt-transport-https curl wget libcurl4-gnutls-dev libudunits2-dev git pandoc libgdal-dev libproj-dev libgeos-dev proj-bin geos-bin gdal-bin libabsl-dev libfontconfig1-dev cmake libharfbuzz-dev libfribidi-dev
- apt-get install -y dirmngr --install-recommends
- cat cran40.pub | tee /etc/apt/trusted.gpg.d/cran_debian_key.asc
- echo "deb http://cloud.r-project.org/bin/linux/debian bookworm-cran40/" | tee -a /etc/apt/sources.list
- apt-get update && apt-get install r-base
- wget "https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-amd64.deb"
- dpkg -i quarto-${QUARTO_VERSION}-linux-amd64.deb
- R -e "install.packages(c('quarto', 'sf', 'tidygeocoder', 'mapview', 'osrm', 'DT'))"
pages:
script:
- rm -rf index_files/ index.html
- R -e "install.packages('quarto')"
- quarto render index.qmd
- mv -v img public/
- mv -v *.html public/
- mv -v index_files public/
artifacts:
paths:
- public
only:
- main
Pour que le cache soit effectif, il y a quelques modifications à faire dans le fichier gitlab-ci.yml
:
image: debian:bookworm-20250610-slim
variables:
QUARTO_VERSION: 1.8.2
R_LIBS_USER: "$CI_PROJECT_DIR/ci/lib"
BUILD_LOGS_DIR: "$CI_PROJECT_DIR/ci/logs/"
before_script:
- export LC_ALL=C.UTF-8
- apt-get update && apt-get install -y apt-transport-https curl wget libcurl4-gnutls-dev libudunits2-dev git pandoc libgdal-dev libproj-dev libgeos-dev proj-bin geos-bin gdal-bin libabsl-dev libfontconfig1-dev cmake libharfbuzz-dev libfribidi-dev
- apt-get install -y dirmngr --install-recommends
- cat cran40.pub | tee /etc/apt/trusted.gpg.d/cran_debian_key.asc
- echo "deb http://cloud.r-project.org/bin/linux/debian bookworm-cran40/" | tee -a /etc/apt/sources.list
- apt-get update && apt-get install -y r-base
- mkdir -p $R_LIBS_USER $BUILD_LOGS_DIR
- echo "R_LIBS='$R_LIBS_USER'" > .Renviron
- wget "https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-amd64.deb"
- dpkg -i quarto-${QUARTO_VERSION}-linux-amd64.deb
- R -e "install.packages(c('quarto', 'sf', 'tidygeocoder', 'mapview', 'osrm', 'DT'))"
pages:
script:
- rm -rf index_files/ index.html
- quarto render index.qmd --log-level debug
- mv -v img public/
- mv -v *.html public/
- mv -v index_files public/
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- $R_LIBS_USER
artifacts:
paths:
- public
only:
- main
C’est la recette équivalente à l’image “maison” que j’ai réalisé pour simplifier le déploiement de mon super notebook python
image: python:3.10-slim-bookworm
pages:
before_script:
- apt-get update && apt-get -y install curl gdal-bin libgdal-dev geos-bin libgeos-dev proj-bin libproj-dev python3-numpy >
- python -m venv .venv # Create virtual environment inside the .venv directory
- source .venv/bin/activate # Activate the environment
- pip install --upgrade pip
- pip install pip-tools
- pip-compile requirements.in
- pip-sync requirements.txt
script:
- export BASE_URL="$CI_PAGES_URL"
- export JUPYTER_BASE_URL="http://127.0.0.1:8888"
- export JUPYTER_TOKEN="montokenrandom"
- jupyter server --IdentityProvider.token='montokenrandom' --notebook-dir="$(pwd)" --Serv>
- jupyter-book build -d --execute --html
- mkdir .public
- cp -r _build/html/* .public
- mv .public public
- echo "Votre document a été déployé à ce lien $CI_PAGES_URL"
artifacts:
paths:
- public
only:
- main
Le Dockerfile ayant servi à la construction est reproduit ici, mais vous pouvez le trouver aussi dans le dépot avec le matériel supplémentaire :
1FROM python:3.10-slim-bookworm
MAINTAINER Sebastien Rey-Coyrehourcq <sebastien.rey-coyrehourcq@univ-rouen.fr>
RUN apt-get update && apt-get install --no-install-recommends -y curl gdal-bin libgdal-dev geos-bin libgeos-dev proj-bin \
libproj-dev python3-numpy gcc g++ make nodejs texlive-latex-base latexmk wget npm net-tools gosu graphviz bash webp
2ARG DOCKER_USER=myst-user
RUN wget -c https://github.com/nicolas-van/multirun/releases/download/1.1.3/multirun-x86_64-linux-gnu-1.1.3.tar.gz -O - | tar -xz
3RUN mv multirun /bin
4RUN useradd -ms /bin/bash "$DOCKER_USER"
USER "$DOCKER_USER"
WORKDIR /home/"$DOCKER_USER"
ENV PATH="/home/myst-user/.local/bin:$PATH"
5COPY requirements.in .
RUN pip install --upgrade pip
RUN pip install --user pip-tools
RUN pip-compile requirements.in
RUN pip-sync requirements.txt
RUN pip install --user --no-cache-dir -r requirements.txt
RUN pip install numpy
RUN pip install gdal==$(gdal-config --version)
COPY docker-entrypoint.sh .
6RUN sed "s/\$DOCKER_USER/$DOCKER_USER/g" -i docker-entrypoint.sh
RUN chmod 755 docker-entrypoint.sh
7WORKDIR /home/"$DOCKER_USER"
8ENTRYPOINT ["sh", "docker-entrypoint.sh"]
9CMD ["multirun", "jupyter-lab --IdentityProvider.token='512ac78f14e1141db1fac17e8b4099c1e5bc7d589518b38c' --ServerApp.allow_origin='http://localhost:3000' --ip=0.0.0.0 --port 8888 --no-browser &"]
- 1
- L’image de référence utilisé
- 2
- Au cas ou on aurait besoin de lancer plusieurs services dans le même container
- 3
-
Dans les bonnes pratique il est recommandé d’utiliser Docker en mode utilisateur et non pas en root, c’est pourquoi on définit un utilisateur
myst-user
qui va être utilisé tout au long du Dockerfile. - 4
-
Commande pour créer l’utilisateur
myst-user
au sein de l’image - 5
- On copie le fichier Requirements python qui contient les dépendances nécessaire à Jupyter Lab
- 6
-
Le fichier
docker-entrypoint.sh
contient le script qui permet de lancer les futures commandes qui seront passés lors dudocker run
avec l’utilisateurmyst-user
dans le container - 7
-
Le répertoire par défaut pour l’utilisateur sera
/home/myst-user
- 8
- Le point de passage de toutes les commandes futures
- 9
- La commande lancé par défaut, lorsque le container est lancé, même sans argument autre est le serveur Jupyter Lab