Packaging¶
Use boxen build on the host to turn a vendor VM disk into a local Docker image. The separate boxen package command runs inside the builder and is normally invoked automatically.
Choose the inputs¶
You need a disk, a profile, and any extraFiles declared by the profile. The disk may be QCOW2 or another format accepted by qemu-img convert, such as VMDK. Boxen converts it into /boxen/disk.qcow2.
There are three ways to select a profile:
| Selection | Example | Behavior |
|---|---|---|
| File path | --profile ./profiles/router.yaml |
Loads that YAML file when the path exists. |
| Embedded name | --profile nvidia_cumulusvx |
Looks through profiles embedded in the binary. |
| Automatic | Omit --profile |
Matches diskPatterns against the disk basename. |
The current lookup checks embedded names and disk patterns together as it walks the embedded files. A disk pattern encountered earlier can win even when a different embedded name was supplied. Use an existing profile file path when you need unambiguous selection.
Extra files are found at the listed path if it exists, otherwise beside the disk under the listed basename. They arrive in /boxen under their basenames. Use distinct names and avoid disk.qcow2, which is reserved for the converted disk. Also give the source disk a vendor filename rather than the literal disk.qcow2: the current conversion routine uses that name for its output and deletes the transferred source afterward.
Name the image¶
boxen build \
--disk /path/to/cumulus-linux-5.16.1-vx-amd64-qemu.qcow2 \
--profile nvidia_cumulusvx \
--reg ghcr.io/my-org \
--tag 5.16.1
This produces ghcr.io/my-org/boxen-nvidia_cumulusvx:5.16.1 in the local Docker daemon. --reg sets the image name prefix; it does not push to a registry.
The name is [registry/]boxen-<profile.name>:<tag>. With the default latest tag, a resolved disk version becomes the tag if one is available. An explicit non-latest tag wins. Passing --tag latest still allows version resolution to replace it.
What happens during a build¶
- Resolve inputs. The CLI checks the disk path, reads the profile, and extracts
resolvedVersionusingversionPattern. - Start the builder. The host listens on TCP 10329 and launches
boxen-<profile.name>-builderas a privileged Docker container. - Transfer files. The agent requests the profile, disk, and extra files. It writes
profile.yamlfor the future runtime. - Convert the disk.
qemu-img convert -O qcow2createsdisk.qcow2and the transferred source copy is removed. - Prepare and boot.
prePackagingCommandsrun through/bin/bash -c, then QEMU starts with packaging-specific arguments. - Automate the console.
packaging.processhandles dialogs, credentials, and baseline configuration over serial TCP 5001. - Finalize the disk. Boxen closes its console, kills QEMU, optionally runs
virt-sparsify --compress, and executespostPackagingCommands. - Commit the image. The host changes the entrypoint to
/boxen/boxen run, records applicable exposed ports, commits the image, and removes the completed builder.
The profile controls guest configuration and saving it. Ending a write step means the lines were sent; add a readUntil step to confirm a save or commit completed. A guest shutdown step is useful when the OS needs an orderly flush before QEMU stops.
Sparsification¶
Set packaging.shrinkify: true to reclaim unused disk space and compress the QCOW2 image after the guest stops. It can take more than ten minutes and depends on libguestfs and the host kernel mounts. It is disabled when omitted. The accepted key is shrinkify; older sparsify keys in some profiles are not wired to this setting.
Inspect the boot interactively¶
This transfers and converts the disk, runs pre-packaging commands, and boots the VM. It skips packaging console automation, sparsification, image commit, and automatic builder removal. Your terminal attaches to the serial console using the container's telnet client.
Leave telnet with Ctrl+], then q. Reconnect with:
After inspection, remove that specific builder before starting another build with the same profile:
If a build fails¶
The failed builder can remain for inspection. Capture its logs and console transcript before removing it:
docker logs boxen-<profile-name>-builder
docker cp boxen-<profile-name>-builder:/boxen/package.console.log ./package.console.log
See troubleshooting for RPC connectivity, prompt matching, and disk utility failures. After a successful build, follow running a lab or image management.