
Présentation de cette formation
Section intitulée « Présentation de cette formation »Packer est l'outil HashiCorp de référence pour créer des images machine identiques sur de multiples plateformes (Docker, AWS, Azure, GCP, Proxmox, etc.). Cette formation vous accompagne du premier template jusqu'à l'automatisation complète de vos workflows de création d'images.
Contrairement à une documentation classique, cette formation suit une progression pédagogique : chaque module s'appuie sur les précédents, avec des exemples pratiques testables immédiatement.
Avant de démarrer, voici le profil visé, les prérequis et le volume de cette formation Packer. Ce tableau vous dit en un coup d'oeil si le parcours correspond à votre niveau et au temps que vous pouvez y consacrer.
| Public | Développeurs, DevOps, SRE, équipes plateforme |
| Prérequis | Terminal Linux, bases Docker (pour les exemples) |
| Durée totale | ~4 heures (7 modules) |
| Approche | Théorie + templates .pkr.hcl + labs Docker |
Ce que vous apprendrez
Section intitulée « Ce que vous apprendrez »À la fin de cette formation, vous serez capable de :
- Créer des images reproductibles multi-plateformes
- Écrire des templates HCL2 clairs et maintenables
- Paramétrer avec variables, locals et fonctions built-in
- Configurer provisioners (shell, file, Ansible)
- Enchaîner des post-processors (compress, manifest, Docker)
- Intégrer Packer dans vos pipelines CI/CD
Vue d'ensemble de la formation
Section intitulée « Vue d'ensemble de la formation »Les 7 modules suivent une progression du concept à l'industrialisation. Chaque ligne indique le niveau, la durée estimée et la capacité concrète acquise à la fin du module. Suivez-les dans l'ordre si vous débutez, ou sautez directement au module qui vous manque.
| Module | Titre | Niveau | Durée | Ce que vous saurez faire |
|---|---|---|---|---|
| 1 | Concepts et cas d'usage | Débutant | 30 min | « Je comprends pourquoi Packer et quand l'utiliser » |
| 2 | Installation multi-plateforme | Débutant | 20 min | « Packer est installé et je peux l'exécuter » |
| 3 | Templates HCL2 | Débutant | 45 min | « Je sais écrire un template HCL2 de base » |
| 4 | Variables et fonctions | Intermédiaire | 45 min | « Je paramètre mes builds avec variables et fonctions » |
| 5 | Provisioners | Intermédiaire | 45 min | « Je configure mes images avec shell, file ou Ansible » |
| 6 | Post-processors | Intermédiaire | 45 min | « J'enchaîne des actions post-build (compress, push Docker) » |
| 7 | Bonnes pratiques | Intermédiaire | 40 min | « Mes templates sont maintenables et intégrés en CI/CD » |
Le parcours de formation
Section intitulée « Le parcours de formation »Module 1 · Concepts
Comprendre Packer et son écosystème
Golden images, philosophie HashiCorp, comparaison avec Dockerfile, principaux builders.
Module 2 · Installation
Installer Packer sur votre système
Binaire officiel, asdf, gestionnaires de paquets, validation de l'installation.
Module 3 · Templates HCL2
Écrire votre premier template
Anatomie d'un template, blocs source et build, builder Docker, premier build.
Module 4 · Variables et fonctions
Paramétrer vos builds
Variables, locals, pkrvars, fonctions built-in, expressions conditionnelles.
Module 5 · Provisioners
Configurer vos images
Shell, file, Ansible, provisioner de nettoyage, bonnes pratiques de configuration.
Module 6 · Post-processors
Actions post-build
Compress, manifest, checksum, docker-import, docker-tag, docker-push, chaînage.
Module 7 · Bonnes pratiques
Industrialiser vos templates
Structure projet, Makefile, debug, sécurité des secrets, intégration CI/CD.
FAQ Packer
Questions fréquentes
Réponses aux questions courantes sur Packer, dépannage, comparaisons avec d'autres outils.
Programme détaillé
Section intitulée « Programme détaillé »Module 1, Concepts et cas d'usage
Section intitulée « Module 1, Concepts et cas d'usage »Le premier module pose les fondations. Vous comprendrez pourquoi Packer existe, ce qu'est une « golden image », et quand utiliser Packer plutôt qu'un Dockerfile ou un script shell.
| Thème | Contenu |
|---|---|
| Problématique | Dérive de configuration, images non reproductibles |
| Golden images | Définition, avantages, immutable infrastructure |
| Philosophie HashiCorp | Workflow Plan → Apply, idempotence |
| Builders | Docker, AWS, Azure, GCP, Proxmox, QEMU |
| Comparaison | Packer vs Dockerfile vs scripts shell |
Module 2, Installation multi-plateforme
Section intitulée « Module 2, Installation multi-plateforme »Installation de Packer sur Linux, macOS et Windows. Nous recommandons asdf pour gérer plusieurs versions côte à côte.
| Méthode | Commande |
|---|---|
| asdf (recommandé) | asdf plugin add packer && asdf install packer latest |
| Binaire officiel | Téléchargement depuis releases.hashicorp.com |
| Homebrew (macOS) | brew install packer |
| Chocolatey (Windows) | choco install packer |
Module 3, Templates HCL2
Section intitulée « Module 3, Templates HCL2 »Le cœur de Packer : les templates HCL2. Vous apprendrez la structure
d'un fichier .pkr.hcl, les blocs source et build, et comment créer
votre première image Docker.
| Bloc | Rôle |
|---|---|
packer {} | Configuration Packer, plugins requis |
source | Définition du builder (Docker, AWS, etc.) |
build | Orchestration des sources, provisioners, post-processors |
source "docker" "ubuntu" { image = "ubuntu:24.04" commit = true}
build { sources = ["source.docker.ubuntu"]}Module 4, Variables et fonctions
Section intitulée « Module 4, Variables et fonctions »Rendez vos templates flexibles et réutilisables avec les variables, locals et fonctions built-in.
| Concept | Exemple |
|---|---|
| Variables | variable "image_tag" { default = "latest" } |
| Locals | local { timestamp = formatdate("YYYYMMDDhhmmss", timestamp()) } |
| Fonctions | upper(), lower(), replace(), join(), file() |
| Conditionnelles | condition ? true_val : false_val |
Module 5, Provisioners
Section intitulée « Module 5, Provisioners »Les provisioners configurent l'image après sa création : installation de paquets, copie de fichiers, exécution de playbooks Ansible.
| Provisioner | Usage |
|---|---|
| shell | Commandes bash/sh, scripts |
| file | Copie de fichiers locaux vers l'image |
| ansible | Exécution de playbooks Ansible |
| shell-local | Commandes sur la machine hôte |
Module 6, Post-processors
Section intitulée « Module 6, Post-processors »Les post-processors agissent après le build : compression, génération de manifest, push vers un registry Docker.
| Post-processor | Résultat |
|---|---|
| compress | Archive .tar.gz de l'image |
| manifest | Fichier JSON avec métadonnées du build |
| checksum | Hash SHA256 pour vérification d'intégrité |
| docker-import | Importation dans Docker Engine |
| docker-tag | Tag de l'image Docker |
| docker-push | Push vers Docker Hub/Registry privé |
Module 7, Bonnes pratiques
Section intitulée « Module 7, Bonnes pratiques »Industrialisez vos templates avec une structure projet propre, un Makefile, des techniques de debug et l'intégration CI/CD.
| Thème | Contenu |
|---|---|
| Structure projet | Organisation des fichiers .pkr.hcl |
| Makefile | Cibles validate, build, clean |
| Debug | Variables PACKER_LOG, mode step-by-step |
| Secrets | Variables d'environnement, pas de hardcode |
| CI/CD | GitHub Actions, GitLab CI/CD |
Par où commencer ?
Section intitulée « Par où commencer ? »Suivez les modules dans l'ordre, en commençant par les concepts. Prenez le temps de créer les labs Docker pour chaque module.
Premier module : Concepts et cas d'usage
Si vous connaissez déjà Packer mais souhaitez approfondir, allez directement au module 4 (variables) ou au module 5 (provisioners).
Module recommandé : Variables et fonctions
Consultez directement les bonnes pratiques pour structurer vos projets et intégrer Packer en CI/CD.
Module recommandé : Bonnes pratiques
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions les plus posées sur Packer : différence avec Dockerfile ou Terraform, licence, installation, provisioners et intégration CI/CD.
Ce que Packer fait
| Fonction | Exemple |
|---|---|
| Création d'images | AMI AWS, images Docker, VM Azure |
| Multi-plateforme | 1 template → plusieurs images |
| Automatisation | Build reproductible sans intervention |
| Golden images | Image de base standardisée |
Exemple rapide
source "docker" "ubuntu" {
image = "ubuntu:24.04"
commit = true
}
build {
sources = ["source.docker.ubuntu"]
provisioner "shell" {
inline = ["apt-get update && apt-get install -y curl"]
}
}
Comparaison
| Critère | Packer | Dockerfile |
|---|---|---|
| Cible | Multi-plateforme | Docker uniquement |
| Format | HCL2 | DSL spécifique |
| Provisioners | Shell, Ansible, Chef, Puppet | RUN uniquement |
| Sortie | AMI, VMDK, OCI, Docker... | Image Docker |
| Écosystème | HashiCorp | Docker/OCI |
| Cas d'usage | Golden images multi-cloud | Conteneurs applicatifs |
Quand utiliser quoi ?
- Dockerfile : applications conteneurisées, développement local
- Packer : golden images multi-cloud, immutable infrastructure
- Les deux : Packer peut utiliser Docker comme builder de test
Exemple identique
# Dockerfile
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y curl
# Packer HCL2
source "docker" "ubuntu" {
image = "ubuntu:24.04"
commit = true
}
build {
sources = ["source.docker.ubuntu"]
provisioner "shell" {
inline = ["apt-get update && apt-get install -y curl"]
}
}
Linux (recommandé : asdf)
# Avec asdf (gestion de versions)
asdf plugin add packer
asdf install packer latest
asdf set --home packer latest
# Ou téléchargement direct
wget https://releases.hashicorp.com/packer/1.15.0/packer_1.15.0_linux_amd64.zip
unzip packer_1.15.0_linux_amd64.zip
sudo mv packer /usr/local/bin/
macOS
# Homebrew
brew install packer
Windows
# Chocolatey
choco install packer
# Ou Scoop
scoop install packer
Vérification
packer --version
# Packer v1.15.0
.pkr.hcl qui définit comment créer une image.Blocs principaux
| Bloc | Rôle | Obligatoire |
|---|---|---|
packer {} |
Configuration, plugins requis | Optionnel |
source |
Définition du builder | Oui |
build |
Orchestration du build | Oui |
variable |
Paramètres d'entrée | Optionnel |
locals |
Valeurs calculées | Optionnel |
Exemple minimal
packer {
required_plugins {
docker = {
version = ">= 1.0.0"
source = "github.com/hashicorp/docker"
}
}
}
source "docker" "ubuntu" {
image = "ubuntu:24.04"
commit = true
}
build {
sources = ["source.docker.ubuntu"]
}
HCL2 vs JSON
| Aspect | HCL2 | JSON (legacy) |
|---|---|---|
| Lisibilité | Excellente | Difficile |
| Commentaires | # ou // |
Non supportés |
| Fonctions | Built-in | Limitées |
| Statut | Recommandé | Déprécié |
Workflow de validation
# 1. Télécharger les plugins requis
packer init .
# 2. Vérifier le formatage
packer fmt -check .
# 3. Valider la syntaxe et la cohérence
packer validate .
# Optionnel : avec des variables
packer validate -var "image_tag=latest" .
Ce que valide Packer
| Commande | Vérifie |
|---|---|
packer init |
Plugins disponibles et téléchargés |
packer fmt -check |
Formatage HCL conforme |
packer validate |
Syntaxe, références, cohérence |
En CI/CD
# Échouer au premier problème
packer init . && packer fmt -check . && packer validate .
Exemple de sortie
$ packer validate .
The configuration is valid.
$ packer validate broken.pkr.hcl
Error: Unknown source type "docker.ubuntu"
Builders principaux
| Builder | Plateforme | Sortie |
|---|---|---|
| docker | Docker Engine | Image OCI |
| amazon-ebs | AWS | AMI |
| azure-arm | Azure | Managed Image |
| googlecompute | GCP | Compute Image |
| qemu | KVM/Proxmox | QCOW2 |
| vmware-iso | VMware | VMDK |
| virtualbox-iso | VirtualBox | OVA |
| lxc / lxd | Conteneurs Linux | Image LXC/LXD |
| null | Test | Aucune (dry-run) |
Installation des plugins
packer {
required_plugins {
docker = {
version = ">= 1.0.0"
source = "github.com/hashicorp/docker"
}
amazon = {
version = ">= 1.0.0"
source = "github.com/hashicorp/amazon"
}
}
}
Multi-plateforme
Un même template peut cibler plusieurs builders :build {
sources = [
"source.docker.ubuntu",
"source.amazon-ebs.ubuntu"
]
}
Déclaration
variable "image_tag" {
type = string
default = "latest"
description = "Tag de l'image Docker"
}
variable "packages" {
type = list(string)
default = ["curl", "wget", "vim"]
}
Utilisation
source "docker" "app" {
image = "ubuntu:${var.image_tag}"
commit = true
}
Fournir des valeurs
| Méthode | Exemple |
|---|---|
| CLI | packer build -var "image_tag=1.0" . |
| Fichier | packer build -var-file=prod.pkrvars.hcl . |
| Environnement | export PKR_VAR_image_tag=1.0 |
Locals (valeurs calculées)
locals {
timestamp = formatdate("YYYYMMDDhhmmss", timestamp())
image_name = "app-${var.image_tag}-${local.timestamp}"
}
Provisioners principaux
| Provisioner | Usage |
|---|---|
| shell | Commandes bash/sh, scripts |
| file | Copie de fichiers vers l'image |
| ansible | Exécution de playbooks |
| shell-local | Commandes sur la machine hôte |
Exemple
build {
sources = ["source.docker.ubuntu"]
provisioner "file" {
source = "config/app.conf"
destination = "/etc/app/app.conf"
}
provisioner "shell" {
inline = [
"apt-get update",
"apt-get install -y nginx"
]
}
provisioner "ansible" {
playbook_file = "playbooks/configure.yml"
}
}
Ordre d'exécution
Les provisioners s'exécutent dans l'ordre de déclaration :file→ copie les fichiersshell→ installe les paquetsansible→ configure l'application
Logs détaillés
# Activer tous les logs
export PACKER_LOG=1
packer build .
# Ou en une ligne
PACKER_LOG=1 packer build .
Mode interactif
# Pause entre chaque étape
packer build -debug .
# Pause configurable
PACKER_LOG=1 PACKER_LOG_PATH=packer.log packer build -debug .
Gestion des erreurs
# Demander quoi faire en cas d'erreur
packer build -on-error=ask .
# Options : abort, retry, cleanup
Problèmes courants
| Symptôme | Cause probable |
|---|---|
| Timeout SSH | Firewall, clé SSH incorrecte |
| Command not found | Chemin non dans PATH |
| Permission denied | Utilisateur non root, sudo requis |
| Plugin not found | packer init . pas exécuté |
| Variable undefined | Variable déclarée mais non valorisée |
Post-processors principaux
| Post-processor | Action |
|---|---|
| compress | Archive .tar.gz de l'image |
| manifest | Fichier JSON avec métadonnées |
| checksum | Hash SHA256 pour intégrité |
| docker-import | Import dans Docker Engine |
| docker-tag | Ajout de tags à l'image |
| docker-push | Push vers registry |
Exemple simple
build {
sources = ["source.docker.ubuntu"]
post-processor "manifest" {
output = "manifest.json"
}
}
Chaînage de post-processors
post-processors {
post-processor "docker-import" {
repository = "myapp"
tag = "latest"
}
post-processor "docker-push" {
login = true
login_server = "registry.example.com"
login_username = var.registry_user
login_password = var.registry_pass
}
}
Le chaînage garantit que chaque étape utilise le résultat de la précédente.GitHub Actions
name: Build Image
on: [push]
jobs:
packer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Packer
uses: hashicorp/setup-packer@v3
with:
version: "1.15.0"
- name: Init
run: packer init .
- name: Validate
run: packer fmt -check . && packer validate .
- name: Build
run: packer build .
env:
PKR_VAR_image_tag: ${{ github.sha }}
GitLab CI/CD
packer-build:
image: hashicorp/packer:1.15.0
script:
- packer init .
- packer fmt -check .
- packer validate .
- packer build .
variables:
PKR_VAR_image_tag: $CI_COMMIT_SHORT_SHA
cache:
paths:
- .packer.d/
Bonnes pratiques CI/CD
- Cacher le répertoire des plugins
- Variables d'environnement pour les secrets
- Validation avant le build
- Manifest pour traçabilité
amazon-ebs.Template minimal
packer {
required_plugins {
amazon = {
version = ">= 1.0.0"
source = "github.com/hashicorp/amazon"
}
}
}
variable "aws_region" {
default = "eu-west-3"
}
source "amazon-ebs" "ubuntu" {
region = var.aws_region
instance_type = "t3.micro"
source_ami_filter {
filters = {
name = "ubuntu/images/*ubuntu-jammy-22.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["099720109477"] # Canonical
}
ssh_username = "ubuntu"
ami_name = "my-app-{{timestamp}}"
}
build {
sources = ["source.amazon-ebs.ubuntu"]
provisioner "shell" {
inline = ["sudo apt-get update && sudo apt-get install -y nginx"]
}
}
Authentification
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG..."
packer build .
Arborescence
projet-packer/
├── common.pkr.hcl # Plugins, config commune
├── variables.pkr.hcl # Déclarations de variables
├── locals.pkr.hcl # Valeurs calculées
├── docker.pkr.hcl # Source Docker
├── aws.pkr.hcl # Source AWS (optionnel)
├── build.pkr.hcl # Blocs build
├── dev.pkrvars.hcl # Variables dev
├── prod.pkrvars.hcl # Variables prod
├── scripts/
│ ├── setup.sh
│ └── cleanup.sh
├── config/
│ └── app.conf
└── Makefile
Makefile
.PHONY: init validate build clean
init:
packer init .
validate: init
packer fmt -check .
packer validate .
build: validate
packer build -var-file=dev.pkrvars.hcl .
build-prod: validate
packer build -var-file=prod.pkrvars.hcl .
clean:
rm -f manifest.json *.tar.gz
Utilisation
make build # Build dev
make build-prod # Build prod
Variables sensibles
variable "docker_password" {
type = string
sensitive = true # Masqué dans les logs
}
Bonnes pratiques
| Méthode | Sécurité | Usage |
|---|---|---|
| Env vars | ✅ Bonne | PKR_VAR_password=xxx packer build . |
| CI Secrets | ✅ Excellente | GitHub Secrets, GitLab CI Variables |
| Vault | ✅ Enterprise | HashiCorp Vault integration |
| CLI -var | ⚠️ Risquée | Visible dans historique shell |
| Fichier committé | ❌ Dangereuse | Jamais en production |
En CI/CD
# GitHub Actions
env:
PKR_VAR_docker_password: ${{ secrets.DOCKER_PASSWORD }}
# GitLab CI
variables:
PKR_VAR_docker_password: $DOCKER_PASSWORD
.gitignore
# Ne jamais committer
*.pkrvars.hcl
!example.pkrvars.hcl
Multi-sources
source "docker" "app" {
image = "ubuntu:24.04"
commit = true
}
source "amazon-ebs" "app" {
region = "eu-west-3"
instance_type = "t3.micro"
# ...
}
build {
sources = [
"source.docker.app",
"source.amazon-ebs.app"
]
provisioner "shell" {
inline = ["echo 'Hello from ${source.type}'"]
}
}
Contrôle du parallélisme
# Limiter à 2 builds simultanés
packer build -parallel-builds=2 .
# Un seul build à la fois
packer build -parallel-builds=1 .
Avantages
- Gain de temps : Docker et AWS se buildent simultanément
- Même configuration : provisioners partagés
- Artefacts séparés : chaque builder produit son image
| Critère | Packer | Terraform |
|---|---|---|
| Rôle | Construire des images machine | Provisionner l'infrastructure |
| Produit | AMI, image Docker, QCOW2, VMDK | VM, réseau, stockage, DNS |
| Moment | Avant le déploiement (build) | Au déploiement (apply) |
| Langage | HCL2 | HCL2 |
Workflow combiné
- Packer crée une image durcie et pré-configurée (golden image).
- Terraform déploie des instances à partir de cette image.
Licence
Depuis août 2023, Packer est distribué sous BUSL-1.1 (Business Source License), en remplacement de la licence MPL-2.0 historique. En pratique :- L'usage reste libre et sans coût pour construire vos images, y compris en entreprise et en CI/CD.
- La seule restriction vise à concurrencer commercialement les produits HashiCorp, ce qui ne concerne pas les équipes qui utilisent Packer pour leurs propres besoins.
| Aspect | Packer | Vagrant |
|---|---|---|
| Objectif | Construire des images machine | Orchestrer des VMs de dev |
| Cible | Production, cloud, multi-plateforme | Poste de développement local |
| Produit | AMI, image Docker, QCOW2, box | VM lancée depuis une box |
| Cycle de vie | Build ponctuel d'un artefact | up, ssh, halt, destroy |
Comment ils s'articulent
Packer peut générer les box que Vagrant consomme, grâce à son post-processorvagrant :post-processor "vagrant" {
output = "ma-box.box"
}
En pratique : Packer standardise l'image de base une fois pour toutes, Vagrant l'instancie en local pour que chaque développeur travaille dans le même environnement.Ressources complémentaires
Section intitulée « Ressources complémentaires »- Site officiel : packer.io
- Documentation : developer.hashicorp.com/packer/docs
- Référence HCL2 : developer.hashicorp.com/packer/docs/templates/hcl_templates
- Builders : developer.hashicorp.com/packer/integrations
- GitHub Packer : github.com/hashicorp/packer