Skip to content

Repository files navigation

Infrastructure DevContainer

Image de développement pour l'Infrastructure as Code (IaC) du monorepo infrastructure. Construite sur Rocky Linux 10 (UBI) et publiée sur ghcr.io/stackopshq/devcontainer:latest.

🧰 Outils installés

Les versions sont alignées sur celles de .tasks.d/install/Taskfile.yml et du groupe ansible de pyproject.toml du repo stackopshq/infrastructure (GitHub).

Les outils Kubernetes (kubectl, helm, kustomize, flux) ne sont volontairement pas embarqués : aucun playbook ni pipeline du repo consommateur ne les utilise. Ils restent installables à la demande avec task install:helm, task install:kubectl, etc.

CatégorieOutilVersion
Task runnerTaskv3.49.1
RuntimeNode.jsv22.23.2
Pythonuv + Python0.11.3 / 3.13.9
IaCOpenTofuv1.11.5
IaCTerraformv1.15.6
IaCterraform-docsv0.21.0
SecretsVault (OpenBao-compatible)v1.21.4
Ansibleansible-core2.20.7
Ansibleansible-lint26.4.0
Ansiblemolecule (+ plugins)26.4.0

Outils système : git, curl, jq, gnupg2, unzip/tar/xz, gcc, libffi/openssl/cairo-devel, vi (via vim-minimal, il n'y a pas de vim), bind-utils, net-tools, bash-completion.

🔒 Intégrité des artefacts

Chaque binaire téléchargé est vérifié contre une empreinte SHA256 épinglée dans le Containerfile, à côté de sa version. Ces empreintes proviennent des fichiers de sommes publiés en amont pour l'artefact linux/amd64 exact.

Un artefact modifié en amont, un miroir compromis ou un téléchargement tronqué font échouer le build au lieu de produire une image altérée. Version et empreinte se mettent donc à jour ensemble : bumper l'une sans l'autre casse le build, et c'est voulu.

L'image de base est elle aussi épinglée par digest (@sha256:...), ce qui rend le build reproductible dans le temps.

👤 Utilisateur

  • Par défaut : root, requis par les jobs CI GitLab qui écrivent dans l'arbre de build partagé (/builds/...).
  • VS Code Dev Container : devops (UID/GID 1000/1000, sudo sans mot de passe) via "containerUser" dans devcontainer.json.

📁 Structure

.
├── Containerfile # Build multi-stage, versions et empreintes
├── scripts/
│ ├── fetch.sh # Téléchargement + vérification SHA256 + extraction
│ ├── install-base.sh # Paquets système et utilisateur de l'image finale
│ └── finalize.sh # Exposition des outils uv, complétions, vérifications
├── devcontainer.json # Configuration VS Code Dev Containers
├── .github/workflows/ # CI GitHub Actions (build + push GHCR)
└── README.md

🏗️ Architecture du build

Le build est multi-stage. Chaque outil a son propre stage t-<outil> qui le télécharge, vérifie son empreinte et dépose le binaire dans /out. Le stage final ne récupère que ces binaires : les archives, les décompresseurs et les caches de téléchargement restent en amont.

 ┌─ t-vault ─┐
base (digest) ───┤ t-terraform├─┐
│ └─ t-... ───┘ ├──> image finale (un COPY par outil)
├────────────── t-node ────┤
└────────────── python-tools ─┘

Trois conséquences pratiques :

  • Cache granulaire au build : bumper Terraform ne reconstruit que le stage t-terraform, pas Ansible ni Node.
  • Delta minimal au pull : chaque outil est copié par un COPY distinct, donc il occupe son propre blob. Bumper Terraform ne fait re-télécharger que ses 117 Mo aux consommateurs, au lieu de l'ensemble des binaires. Ne pas regrouper ces COPY : la couche agrégée annulerait ce bénéfice.
  • Parallélisme : sous BuildKit (la CI), les stages t-* se construisent simultanément. Podman en local les enchaîne, le résultat est identique.

Vault et Node sont les deux seuls binaires livrés non strippés en amont : leurs stages retirent les tables de symboles, ce qui économise 149 Mo sans coût au démarrage (contrairement à une compression type UPX).

La toolchain de compilation (gcc, *-devel) est volontairement conservée dans l'image finale : le dépôt consommateur lance uv sync, qui compile des extensions Python natives dans le conteneur.

🔨 Build local

podman build -t ghcr.io/stackopshq/devcontainer:latest -f Containerfile .

Le stage final exécute scripts/finalize.sh, qui appelle chaque outil installé. Un binaire manquant ou un environnement uv cassé fait échouer le build plutôt que de se manifester au premier usage.

🚀 CI/CD (GitHub Actions)

.github/workflows/build-devcontainer.yml construit l'image et la pousse sur GHCR (ghcr.io/${{ github.repository }}).

Déclencheurs :

  • Push sur main/mastersiContainerfile, scripts/** ou le workflow changent.
  • Tag git v* → image taggée avec le tag (release versionnée).
  • Déclenchement manuel (workflow_dispatch).

Tags publiés : :latest, :sha-<short>, et :<git-tag> sur les tags git.

📥 Pull de l'image

podman pull ghcr.io/stackopshq/devcontainer:latest

Si le package GHCR est privé : podman login ghcr.io avec un PAT GitHub disposant du scope read:packages.

➕ Ajouter un outil

  1. Ajouter <OUTIL>_VERSION et <OUTIL>_SHA256 dans le bloc d'ARG en tête du Containerfile, avec un commentaire # renovate:. L'empreinte se récupère dans le fichier de sommes publié par le projet amont.
  2. Ajouter un stage t-<outil> qui appelle fetch <url> <sha256> <binaire>.
  3. Ajouter un COPY --from=t-<outil> /out/ /usr/local/bin/ dans le stage final, en le plaçant selon la fréquence de mise à jour attendue (les plus volatils en dernier).
  4. Ajouter une ligne check dans scripts/finalize.sh, et sa complétion bash si l'outil en fournit une.
  5. Mettre à jour le tableau des versions ci-dessus.

About

DevContainer image for IaC (Ansible, OpenTofu/Terraform, Kubernetes, Vault)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages