跳转至

Packer 镜像构建

一句话概述:Packer 是 HashiCorp 出品的自动化镜像构建工具,用代码定义镜像内容,一次构建可以输出多个平台的镜像(AWS AMI、Docker、VMware 等)。

核心知识点

概念白话解释
Template模板 = 描述镜像怎么构建的配置文件(HCL 或 JSON)
Builder构建器 = 负责创建特定平台镜像(如 amazon-ebs 创建 AWS AMI)
Provisioner供应器 = 镜像里安装软件的方式(Shell 脚本、Ansible 等)
Post-processor后处理器 = 镜像构建完后的处理(压缩、上传等)
Source来源 = HCL 格式中定义构建器的块
Build构建 = HCL 格式中定义构建流程的块
Artifact产物 = 构建出来的镜像文件/ID

安装配置

# macOS
brew install packer  # Homebrew 安装

# 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  # 安装

# 验证
packer version  # 查看版本

基本使用

1. 构建 AWS AMI

# aws-ubuntu.pkr.hcl
packer {
  required_plugins {
    amazon = {
      version = ">= 1.3.0"  # Amazon 插件版本
      source  = "github.com/hashicorp/amazon"  # 插件来源
    }
  }
}

# 变量定义
variable "aws_region" {
  type    = string
  default = "us-east-1"  # 默认区域
}

variable "instance_type" {
  type    = string
  default = "t3.micro"  # 构建用的实例类型
}

# 来源:基于 Amazon EBS 构建 AMI
source "amazon-ebs" "ubuntu" {
  ami_name      = "bioinfo-ubuntu-{{timestamp}}"  # AMI 名称(加时间戳避免重名)
  instance_type = var.instance_type  # 构建用的临时实例类型
  region        = var.aws_region  # 区域
  source_ami_filter {  # 自动查找最新的 Ubuntu AMI
    filters = {
      name                = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"  # Ubuntu 22.04
      root-device-type    = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true  # 用最新的
    owners      = ["099720109477"]  # Canonical 官方
  }
  ssh_username = "ubuntu"  # SSH 用户名
}

# 构建流程
build {
  sources = ["source.amazon-ebs.ubuntu"]  # 使用上面定义的来源

  # Shell 脚本安装软件
  provisioner "shell" {
    inline = [
      "sudo apt-get update",  # 更新包列表
      "sudo apt-get install -y python3 python3-pip",  # 安装 Python
      "sudo pip3 install biopython pandas numpy",  # 安装生信常用包
      "sudo apt-get install -y samtools bwa fastqc",  # 安装生信工具
    ]
  }

  # 执行外部脚本
  provisioner "shell" {
    script = "scripts/setup.sh"  # 执行本地脚本
  }

  # 后处理:生成清单文件
  post-processor "manifest" {
    output = "manifest.json"  # 输出构建清单
  }
}
# 执行构建
packer init .           # 初始化(下载插件)
packer validate .       # 验证配置
packer build .          # 开始构建(会启动 EC2 → 安装软件 → 创建 AMI → 销毁 EC2)
packer build -var "aws_region=ap-southeast-1" .  # 指定变量构建

2. 构建 Docker 镜像

# docker-python.pkr.hcl
source "docker" "python" {
  image  = "python:3.12-slim"  # 基础镜像
  commit = true  # 提交为新镜像
}

build {
  sources = ["source.docker.python"]

  provisioner "shell" {
    inline = [
      "pip install flask gunicorn",  # 安装 Web 框架
      "mkdir -p /app",  # 创建应用目录
    ]
  }

  post-processor "docker-tag" {
    repository = "myapp"  # 镜像名
    tags       = ["latest", "1.0"]  # 标签
  }
}

高级用法

多平台同时构建

source "amazon-ebs" "aws" {
  ami_name      = "myapp-{{timestamp}}"
  instance_type = "t3.micro"
  region        = "us-east-1"
  source_ami    = "ami-xxx"
  ssh_username  = "ubuntu"
}

source "docker" "local" {
  image  = "ubuntu:22.04"
  commit = true
}

build {
  sources = [
    "source.amazon-ebs.aws",  # 同时构建 AWS AMI
    "source.docker.local",     # 和 Docker 镜像
  ]

  provisioner "shell" {
    inline = ["apt-get update && apt-get install -y python3"]  # 两个平台都执行
  }
}

常见报错

报错信息原因解决方法
Error launching source instanceAWS 权限不足检查 IAM 权限(需 EC2、AMI 相关)
Timeout waiting for SSHSSH 连接超时检查安全组是否允许 SSH,加大超时
AMI name already in useAMI 名重复名称加 {{timestamp}}
Plugin not found插件未安装packer init . 安装插件

速查表

# === 核心命令 ===
packer init .          # 初始化插件
packer validate .      # 验证配置
packer build .         # 构建镜像
packer build -var "k=v" .  # 带变量构建
packer fmt .           # 格式化配置文件
packer inspect .       # 查看配置详情

# === 常用供应器 ===
provisioner "shell" { inline = ["cmd"] }     # Shell 命令
provisioner "shell" { script = "setup.sh" }  # 执行脚本
provisioner "file" { source = "f"; destination = "/tmp/f" }  # 上传文件
provisioner "ansible" { playbook_file = "playbook.yml" }     # Ansible

# === 内置函数 ===
{{timestamp}}          # 当前时间戳
{{uuid}}               # 随机 UUID
{{env `VAR`}}          # 读取环境变量

参考:Packer 文档 | 更新于 2026 年