
Ce guide vous explique les concepts fondamentaux de Packer pour que vous puissiez créer vos premières images machine reproductibles. Vous comprendrez comment Packer automatise la création d'images identiques pour le cloud, les VMs locales ou les conteneurs, le tout à partir d'un simple fichier de configuration.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Ce qu'est Packer et pourquoi l'utiliser
- Les trois composants clés : builders, provisioners, post-processors
- Le workflow complet : init → validate → build
- Quand choisir Packer plutôt qu'une autre approche
Prérequis : aucun. Ce guide est une introduction aux concepts.
Qu'est-ce que Packer ?
Section intitulée « Qu'est-ce que Packer ? »Packer est un outil open source créé par HashiCorp qui automatise la création d'images machine. Une image machine est un système d'exploitation déjà installé et configuré, enregistré sous une forme réutilisable (AMI Amazon, image Docker, fichier QCOW2 pour KVM, template Proxmox) à partir de laquelle on instancie des machines identiques. Packer produit ces images à partir d'un fichier de configuration en HCL, sans installation manuelle ni clic dans une interface.
L'apport de Packer est la reproductibilité : le contenu de l'image est décrit dans un fichier versionné, et non dans les souvenirs de la personne qui l'a construite. Deux exécutions du même modèle produisent la même image, sur le poste d'un développeur comme dans une chaîne d'intégration.
| Aspect | Sans Packer | Avec Packer |
|---|---|---|
| Création d'image | Installation manuelle, clics dans l'interface | Une commande : packer build |
| Reproductibilité | "Ça marchait la dernière fois..." | Image identique à chaque build |
| Documentation | Notes personnelles, wiki obsolète | Le template HCL EST la documentation |
| Multi-plateforme | Refaire le travail pour chaque cible | Un template, plusieurs images |
| Versioning | Difficile à tracer | Template versionné avec Git |
Pourquoi utiliser Packer ?
Section intitulée « Pourquoi utiliser Packer ? »Imaginez que vous devez déployer une application sur 50 serveurs. Sans Packer, vous avez deux options :
- Configurer chaque serveur manuellement, long, source d'erreurs, impossible à reproduire
- Utiliser un outil de configuration à chaque démarrage, lent, dépendant du réseau
Avec Packer, vous créez une seule fois une image "golden" qui contient tout : système d'exploitation, dépendances, configuration de sécurité. Ensuite, vous déployez cette image sur vos 50 serveurs en quelques minutes.
Les bénéfices concrets
Section intitulée « Les bénéfices concrets »Construire l'image une seule fois, en amont du déploiement, déplace le travail de configuration hors du démarrage des machines. Chaque serveur démarre alors dans un état déjà validé, ce qui apporte cinq gains mesurables au quotidien.
- Déploiement rapide : une VM prête en secondes au lieu de minutes de configuration
- Cohérence : tous les serveurs sont identiques, pas de "configuration drift"
- Sécurité : les correctifs sont intégrés dans l'image, pas appliqués après coup
- Audit : le template décrit exactement ce qui est installé
- Multi-cloud : une même configuration pour AWS, Azure, GCP, on-premise
Architecture de Packer
Section intitulée « Architecture de Packer »Packer fonctionne avec trois types de composants qui s'exécutent dans un ordre précis. Comprendre cette architecture est essentiel pour écrire des templates efficaces.
Les Builders : créer la machine de base
Section intitulée « Les Builders : créer la machine de base »Le builder est responsable de créer une machine temporaire et de produire une image à partir de celle-ci. Chaque builder est spécifique à une plateforme :
| Builder | Plateforme | Usage typique |
|---|---|---|
amazon-ebs | AWS | AMI pour EC2 |
azure-arm | Azure | Images managées |
googlecompute | GCP | Images Compute Engine |
qemu | KVM/libvirt | Images locales Linux |
proxmox-iso | Proxmox | Templates VM |
docker | Docker | Images conteneur |
virtualbox-iso | VirtualBox | Images de dev |
Packer supporte plus de 52 builders via son système de plugins. Les builders officiels maintenu par HashiCorp sont téléchargés depuis releases.hashicorp.com.
Les Provisioners : configurer l'image
Section intitulée « Les Provisioners : configurer l'image »Les provisioners s'exécutent après que le builder a créé la machine temporaire. Ils configurent le système : installer des paquets, copier des fichiers, exécuter des scripts.
| Provisioner | Description | Cas d'usage |
|---|---|---|
shell | Exécute des commandes shell | Scripts bash simples |
ansible | Exécute des playbooks Ansible | Configuration complexe |
file | Copie des fichiers vers l'image | Fichiers de config |
powershell | Scripts PowerShell | Images Windows |
chef / puppet | Outils de configuration | Écosystèmes existants |
L'ordre des provisioners dans le template détermine leur ordre d'exécution. Packer les exécute séquentiellement.
Les Post-Processors : finaliser l'artefact
Section intitulée « Les Post-Processors : finaliser l'artefact »Les post-processors s'exécutent après la création de l'image pour effectuer des actions supplémentaires :
| Post-Processor | Action |
|---|---|
manifest | Génère un fichier JSON avec les métadonnées du build |
compress | Compresse l'image en archive |
docker-push | Pousse l'image vers Docker Hub ou un registry |
checksum | Calcule les checksums (sha256, md5) |
vagrant | Convertit en box Vagrant |
Le workflow Packer
Section intitulée « Le workflow Packer »Packer suit un workflow en trois étapes que vous utiliserez systématiquement :
-
packer init, Télécharge les plugins requisCette commande lit le bloc
required_pluginsde votre template et télécharge les plugins nécessaires. À exécuter une seule fois par projet (ou quand vous ajoutez un nouveau plugin).Fenêtre de terminal packer init mon-template.pkr.hcl -
packer validate, Vérifie la syntaxe du templateValide que le template HCL est syntaxiquement correct et que toutes les références sont valides. Cette commande ne crée rien, elle vérifie simplement.
Fenêtre de terminal packer validate mon-template.pkr.hcl -
packer build, Construit l'imageExécute le builder, les provisioners et les post-processors pour créer l'image finale.
Fenêtre de terminal packer build mon-template.pkr.hcl
Ce qui se passe pendant un build
Section intitulée « Ce qui se passe pendant un build »Quand vous lancez packer build, voici ce qui se passe en coulisses :
- Création : le builder démarre une machine temporaire (VM, conteneur...)
- Connexion : Packer se connecte via SSH ou WinRM
- Provisionnement : les provisioners configurent la machine
- Capture : le builder crée une image à partir de la machine
- Nettoyage : la machine temporaire est détruite
- Post-traitement : les post-processors s'exécutent sur l'image
Structure d'un template Packer
Section intitulée « Structure d'un template Packer »Un template Packer en HCL (HashiCorp Configuration Language) se compose de plusieurs blocs :
# 1. Bloc packer : version et plugins requispacker { required_version = ">= 1.15.0"
required_plugins { docker = { version = ">= 1.1.0" source = "github.com/hashicorp/docker" } }}
# 2. Variables : rendent le template configurablevariable "image_name" { type = string default = "mon-app" description = "Nom de l'image finale"}
# 3. Source : définit le builder et sa configurationsource "docker" "ubuntu" { image = "ubuntu:22.04" commit = true}
# 4. Build : assemble sources, provisioners et post-processorsbuild { sources = ["source.docker.ubuntu"]
provisioner "shell" { inline = ["apt-get update", "apt-get install -y curl"] }}Packer vs Ansible, Chef et Dockerfile : quelles différences ?
Section intitulée « Packer vs Ansible, Chef et Dockerfile : quelles différences ? »Packer se compare souvent à deux familles d'outils que les débutants confondent avec lui : les gestionnaires de configuration (Ansible, Chef, Puppet) et le Dockerfile. La distinction tient au moment où l'outil agit. Packer configure la machine avant le déploiement et fige le résultat dans une image ; les gestionnaires de configuration agissent pendant ou après le déploiement, sur une machine déjà démarrée. Le Dockerfile, lui, ne produit que des images de conteneur, là où Packer cible aussi les VMs et le cloud.
Packer vs Configuration Management (Ansible, Chef, Puppet)
Section intitulée « Packer vs Configuration Management (Ansible, Chef, Puppet) »| Aspect | Packer | Ansible/Chef/Puppet |
|---|---|---|
| Quand | Avant le déploiement (build time) | Pendant/après le déploiement (run time) |
| Résultat | Image figée | Configuration dynamique |
| Temps de démarrage | Instantané | Dépend de la complexité |
| Dépendances réseau | Non | Oui (repos, registries) |
En pratique : utilisez les deux ensemble. Packer avec Ansible en provisioner pour créer des images, puis Ansible pour les mises à jour légères post-déploiement.
Packer vs Dockerfile
Section intitulée « Packer vs Dockerfile »| Aspect | Packer | Dockerfile |
|---|---|---|
| Scope | VMs + conteneurs | Conteneurs uniquement |
| Multi-plateforme | Oui (AWS, Azure, QEMU...) | Non |
| Provisioners | Shell, Ansible, Chef... | Shell uniquement |
| Écosystème | Intégration Terraform/Vault | Écosystème Docker |
En pratique : pour des conteneurs simples, Dockerfile suffit. Pour des VMs ou des images multi-plateformes, utilisez Packer.
Cas d'usage typiques
Section intitulée « Cas d'usage typiques »Golden Images pour le cloud
Section intitulée « Golden Images pour le cloud »Créez une AMI AWS pré-configurée avec vos outils de monitoring, agents de sécurité et configurations réseau. Chaque nouvelle instance démarre avec tout ce qu'il faut.
Templates pour homelab
Section intitulée « Templates pour homelab »Automatisez la création de templates Proxmox ou VMware pour votre infrastructure personnelle. Un seul template pour créer des VMs identiques.
Images Docker standardisées
Section intitulée « Images Docker standardisées »Créez des images de base avec vos standards d'entreprise : outils de debug, certificats, configuration réseau.
Environnements de développement
Section intitulée « Environnements de développement »Produisez des boxes Vagrant cohérentes pour que tous les développeurs travaillent dans le même environnement.
Pièges courants
Section intitulée « Pièges courants »Quatre erreurs reviennent chez presque tous les débutants sur Packer. Elles ne cassent pas toujours le build de façon évidente, et certaines coûtent surtout du temps ou exposent un secret. Les connaître avant le premier packer build évite de les découvrir en production.
À retenir
Section intitulée « À retenir »- Packer automatise la création d'images machine reproductibles (VMs, conteneurs)
- Builders créent la machine temporaire (AWS, Docker, QEMU, Proxmox...)
- Provisioners configurent l'image (Shell, Ansible, File...)
- Post-processors finalisent l'artefact (compress, push, manifest...)
- Workflow :
packer init→packer validate→packer build - HCL2 est le format de template recommandé depuis v1.7.0
- Golden images = images de référence pré-configurées et validées
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »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.