Packer est un outil open-source créé par HashiCorp qui automatise la création d’images machine pour plusieurs plateformes à partir d’un template unique. Au lieu de configurer manuellement un serveur, prendre un snapshot et espérer avoir documenté chaque étape, Packer codifie l’ensemble du processus. Vous écrivez un template, lancez packer build, et obtenez des images identiques pour AWS, Azure, Docker et VMware — le tout à partir d’une seule définition.
Ce guide couvre l’installation de Packer, la syntaxe des templates HCL, les builders, les provisioners, les builds multi-plateformes et l’intégration de Packer dans des pipelines CI/CD pour une livraison automatisée d’images.
Prérequis
- Packer installé (v1.9+)
- Un compte sur au moins une plateforme cible (AWS, Azure, Docker ou VirtualBox)
- AWS CLI configuré (si vous construisez des AMIs)
- Compréhension de base des images machine et du provisionnement de serveurs
- Familiarité avec la syntaxe HCL (similaire à Terraform)
Installer Packer
Installez depuis le dépôt HashiCorp pour bénéficier des mises à jour automatiques :
# Ubuntu/Debian
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install packer
# macOS
brew install packer
# Vérifier l'installation
packer version
Votre Premier Template Packer
Packer utilise des templates HCL (HashiCorp Configuration Language). Voici un exemple minimal qui construit une image Docker :
# docker-nginx.pkr.hcl
packer {
required_plugins {
docker = {
version = ">= 1.0.0"
source = "github.com/hashicorp/docker"
}
}
}
source "docker" "nginx" {
image = "ubuntu:22.04"
commit = true
}
build {
name = "custom-nginx"
sources = ["source.docker.nginx"]
provisioner "shell" {
inline = [
"apt-get update",
"apt-get install -y nginx curl",
"rm -rf /var/lib/apt/lists/*"
]
}
post-processor "docker-tag" {
repository = "myorg/custom-nginx"
tags = ["latest", "1.0"]
}
}
Construisez-le :
# Initialiser les plugins
packer init docker-nginx.pkr.hcl
# Valider le template
packer validate docker-nginx.pkr.hcl
# Construire l'image
packer build docker-nginx.pkr.hcl
Construire des AMIs AWS avec Packer
Le cas d’usage le plus courant de Packer est la construction d’Amazon Machine Images (AMIs) :
# aws-webserver.pkr.hcl
packer {
required_plugins {
amazon = {
version = ">= 1.2.0"
source = "github.com/hashicorp/amazon"
}
}
}
variable "aws_region" {
type = string
default = "us-east-1"
}
variable "app_version" {
type = string
default = "1.0.0"
}
source "amazon-ebs" "webserver" {
ami_name = "webserver-{{timestamp}}"
instance_type = "t3.micro"
region = var.aws_region
source_ami_filter {
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
owners = ["099720109477"] # Canonical
most_recent = true
}
ssh_username = "ubuntu"
tags = {
Name = "WebServer"
Version = var.app_version
Builder = "Packer"
Environment = "production"
}
}
build {
sources = ["source.amazon-ebs.webserver"]
provisioner "shell" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx nodejs npm certbot",
"sudo systemctl enable nginx"
]
}
provisioner "file" {
source = "config/nginx.conf"
destination = "/tmp/nginx.conf"
}
provisioner "shell" {
inline = [
"sudo cp /tmp/nginx.conf /etc/nginx/nginx.conf",
"sudo nginx -t",
"sudo systemctl restart nginx"
]
}
}
# Construire avec des variables personnalisées
packer build -var "aws_region=eu-west-1" -var "app_version=2.1.0" aws-webserver.pkr.hcl
Types de Provisioners
Packer prend en charge plusieurs provisioners qui s’exécutent à l’intérieur de l’instance de build temporaire :
Provisioner Shell
provisioner "shell" {
scripts = [
"scripts/base-setup.sh",
"scripts/install-app.sh",
"scripts/harden.sh"
]
environment_vars = [
"APP_ENV=production",
"DEBIAN_FRONTEND=noninteractive"
]
}
Provisioner Ansible
provisioner "ansible" {
playbook_file = "ansible/playbook.yml"
extra_arguments = [
"--extra-vars", "app_version=${var.app_version}",
"--tags", "setup,deploy"
]
ansible_env_vars = [
"ANSIBLE_HOST_KEY_CHECKING=False"
]
}
Provisioner File
provisioner "file" {
source = "app/dist/"
destination = "/opt/app/"
}
Scénario réel : Votre entreprise exploite 50 instances EC2 derrière un load balancer. À chaque déploiement, vous construisez une nouvelle AMI avec Packer contenant le dernier code applicatif, la configuration Nginx et les correctifs de sécurité. Terraform effectue ensuite une mise à jour progressive — lançant de nouvelles instances avec la nouvelle AMI et drainant les anciennes. En cas de problème avec la nouvelle image, vous revenez à l’AMI précédente en quelques minutes. Ni connexion SSH aux serveurs, ni dérive de configuration, ni serveurs en flocon de neige.
Builds Multi-Plateformes
Construisez des images pour plusieurs plateformes à partir d’un seul template :
source "amazon-ebs" "aws" {
ami_name = "myapp-aws-{{timestamp}}"
instance_type = "t3.micro"
region = "us-east-1"
source_ami_filter {
filters = { name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" }
owners = ["099720109477"]
most_recent = true
}
ssh_username = "ubuntu"
}
source "docker" "container" {
image = "ubuntu:22.04"
commit = true
}
source "virtualbox-iso" "local" {
iso_url = "https://releases.ubuntu.com/22.04/ubuntu-22.04.3-live-server-amd64.iso"
iso_checksum = "sha256:abcdef..."
ssh_username = "vagrant"
ssh_password = "vagrant"
# ... configuration VirtualBox supplémentaire
}
build {
sources = [
"source.amazon-ebs.aws",
"source.docker.container",
]
provisioner "shell" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx",
]
}
}
Lancez packer build . et Packer construit les deux images en parallèle.
Comparaison Packer vs Alternatives
| Fonctionnalité | Packer | Dockerfile | AWS Image Builder | Ansible (images) |
|---|---|---|---|---|
| Multi-plateforme | Oui (tout cloud + local) | Docker uniquement | AWS uniquement | Oui (avec plugins) |
| Langage de config | HCL | Syntaxe Dockerfile | JSON/YAML | YAML |
| Cache de couches | Non (rebuild complet) | Oui (couches) | Partiel | Non |
| Vitesse de build | Minutes | Secondes-minutes | Minutes | Minutes |
| Support provisioners | Shell, Ansible, Chef, Puppet | Commandes RUN | SSM/AWSTOE | Natif |
| Intégration CI/CD | Excellente | Excellente | AWS seulement | Bonne |
| Sortie immuable | Oui (snapshot) | Oui (image) | Oui (AMI) | Variable |
| Courbe d’apprentissage | Moyenne | Faible | Moyenne | Moyenne |
Quand choisir Packer : Environnements multi-cloud, déploiements basés sur des VM, pipelines d’images golden, ou lorsque vous avez besoin de la même image sur AWS et VMware simultanément.
Pièges et Cas Particuliers
-
Filtres AMI source obsolètes : Si votre
source_ami_filtercorrespond à plusieurs AMIs,most_recent = truegarantit que vous obtenez la plus récente. Sans cela, Packer choisit arbitrairement et vos builds deviennent non déterministes. -
Timeouts de build : Packer attend la connectivité SSH après le lancement de l’instance de build. Les régions cloud lentes ou les groupes de sécurité restrictifs provoquent des timeouts. Augmentez
ssh_timeoutau-delà de la valeur par défaut de 5 minutes si nécessaire. -
L’ordre des provisioners compte : Les provisioners s’exécutent dans l’ordre où ils apparaissent dans le template. Un provisioner
filequi copie vers/opt/app/échouera si le répertoire n’existe pas encore — ajoutez d’abord un provisionershellpour le créer. -
Permissions IAM pour les builds AWS : Packer a besoin de
ec2:RunInstances,ec2:CreateImage,ec2:DescribeImageset de plusieurs autres. Utilisez la politique IAM minimale pour Packer plutôt que de lui accorder un accès admin complet. -
Désenregistrement des anciennes AMIs : Packer crée de nouvelles AMIs mais n’en supprime jamais les anciennes. Sans nettoyage, vous accumulez des centaines d’AMIs inutilisées. Utilisez une politique de cycle de vie ou un script planifié pour désenregistrer les images de plus de N jours.
-
Espace disque pendant les builds : Les instances de build temporaires utilisent la taille de volume racine par défaut. Si votre provisionnement installe de nombreux paquets, le disque se remplit. Ajoutez
launch_block_device_mappingspour augmenter le volume racine.
Résolution de Problèmes
| Problème | Cause | Solution |
|---|---|---|
| ”Timeout waiting for SSH” | Le groupe de sécurité bloque SSH ou l’instance démarre lentement | Vérifiez que le SG autorise le port 22 depuis l’IP du builder ; augmentez ssh_timeout |
| ”AccessDenied” lors de la création d’AMI | Politique IAM sans ec2:CreateImage | Ajoutez les permissions EC2 et EBS requises au rôle IAM |
| Les scripts de provisioner échouent | Le script s’exécute avant la mise à jour des paquets | Ajoutez apt-get update en première étape ; utilisez DEBIAN_FRONTEND=noninteractive |
| Le build réussit mais l’AMI est introuvable | Mauvaise région ou mauvais compte | Vérifiez region dans le bloc source ; utilisez aws ec2 describe-images pour confirmer |
| Build Packer lent | Pas de builds parallèles configurés | Utilisez -parallel-builds=N ou des blocs source séparés pour la parallélisation |
Résumé
- Packer automatise la création d’images machine depuis du code, éliminant la configuration manuelle des serveurs et garantissant des builds reproductibles
- Les templates HCL définissent les sources (où construire), les provisioners (quoi installer) et les post-processors (que faire avec la sortie)
- Les builds multi-plateformes produisent des images identiques pour AWS, Docker et VMware à partir d’un seul template
- Le provisioner Ansible intègre la gestion de configuration existante dans les builds Packer pour les configurations complexes
- L’intégration CI/CD permet des builds d’images automatiques à chaque changement d’infrastructure, créant un pipeline de déploiement immuable
- Associez avec Terraform pour un workflow complet — Packer construit l’image, Terraform la déploie