You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Packer构建Alpine镜像时Shell Provisioner修改无法持久化的问题

Packer QEMU构建Alpine镜像后Shell Provisioner修改不保留的问题

问题现象

基于Alpine Virt ISO(alpine-virt-3.20.3-x86_64.iso)使用Packer QEMU Builder构建qcow2镜像,通过boot_command执行setup-alpine完成网络和磁盘配置,Shell Provisioner脚本执行日志显示成功(输出"good"),但启动最终镜像后,脚本创建的文件、修改的配置均不存在。

相关配置与脚本

Packer配置文件(alpine.pkr.hcl)

packer {
  required_plugins {
    qemu = {
      version = ">= 1.0.10"
      source  = "github.com/hashicorp/qemu"
    }
  }
}

source "qemu" "alpine-demo" {
  iso_url           = "./alpine-virt-3.20.3-x86_64.iso"
  iso_checksum      = "81df854fbd7327d293c726b1eeeb82061d3bc8f5a86a6f77eea720f6be372261"
  output_directory  = "build"
  disk_image        = false
  disk_size         = "5000M"
  disk_interface    = "virtio"
  format            = "qcow2"
  accelerator       = "kvm"
  vm_name           = "alpine-minimal.qcow2"
  machine_type      = "pc"
  net_device        = "virtio-net"
  headless          = false
  cpus              = 1
  boot_key_interval = "10ms"
  shutdown_command  = "poweroff"
  communicator      = "ssh"
  ssh_username      = "root"
  ssh_password      = "alpine"
  ssh_timeout       = "10m"
  memory            = "1024"
  boot_wait         = "10s"
  boot_command = [
    "<wait>root<enter><wait>",
    "setup-alpine<enter><wait>",
    "us<enter>us<enter><wait>",
    "<enter><wait><enter><wait><enter><wait><enter><wait5>",
    "alpine<enter><wait>alpine<enter><wait>",
    "<enter><wait5>",
    "<enter><wait><enter><wait><enter><wait><enter><wait>",
    "yes<enter><wait>",
    "<enter><wait5>",
    "vda<enter><wait>sys<enter><wait>y<enter><wait20>",
  ]
}

build {
  name    = "learn-packer"
  sources = ["source.qemu.alpine-demo"]
  provisioner "shell" {
    script = "./provisioner.sh"
  }
}

Shell Provisioner脚本(provisioner.sh)

#!/bin/sh

set -ex

touch createdfile
echo "JAJAJ" > createdfile

if [ -f ./createdfile ]; then
    echo "good"
else
    echo "bad"
fi

构建与启动命令

  • 构建命令:PACKER_LOG=1 packer build ./alpine.pkr.hcl
  • 启动镜像命令:
qemu-system-x86_64 -name alpinelinux3.19-minimal \
                   -machine type=pc,accel=kvm \
                   -cpu host \
                   -m 512M \
                   -enable-kvm \
                   -nic user \
                   -drive file=./build/alpine-minimal.qcow2,if=virtio,media=disk \
                   -boot c

问题原因

Alpine Virt ISO启动后默认运行在RAM磁盘中,setup-alpine完成磁盘分区和系统安装后,不会自动切换到磁盘系统。此时Packer通过SSH连接的会话仍处于RAM环境,所有脚本修改都保存在内存中,执行poweroff关机后,内存中的数据全部丢失,未写入磁盘镜像。

解决方案

1. 修改boot_command,添加磁盘系统切换与重启步骤

在原boot_command的最后添加以下内容,确保系统重启后切换到磁盘运行:

"<wait>",
"mount /dev/vda2 /mnt<enter><wait>",
"echo '/dev/vda2 / ext4 defaults 0 0' > /mnt/etc/fstab<enter><wait>",
"echo '/dev/vda1 /boot vfat defaults 0 2' >> /mnt/etc/fstab<enter><wait>",
"umount /mnt<enter><wait>",
"reboot<enter><wait30>",

注:这里的vda1是EFI分区,vda2是根分区,对应setup-alpine中选择的sys磁盘布局。

2. 调整Packer连接与等待参数

  • 将ssh_timeout修改为"15m",给重启后的系统足够时间启动SSH服务
  • 将boot_wait调整为"20s",确保系统重启完成后再尝试SSH连接

3. 修改关机命令为安全关机

将shutdown_command = "poweroff"改为:

shutdown_command = "halt -p"

确保系统同步磁盘数据后再关机,避免数据丢失。

4. 脚本使用绝对路径操作文件

修改provisioner.sh,使用绝对路径创建文件,避免当前路径问题:

#!/bin/sh
set -ex

touch /root/createdfile
echo "JAJAJ" > /root/createdfile

if [ -f /root/createdfile ]; then
    echo "good"
else
    echo "bad"
fi

内容的提问来源于stack exchange,提问作者ivans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 21:40:54