When converting images with mender-convert
, you may need to pre-install packages from the distribution’s repositories. This tutorial demonstrates how to install packages during the conversion process using a configuration fragment.
The Challenge
The mender-convert
tool operates in a chroot environment when modifying the rootfs. Direct package installation requires proper chroot setup, especially for cross-architecture builds where qemu-static emulation is needed.
Creating the Configuration Fragment
Create a configuration file that hooks into the platform modification phase:
cat > input/package_install_config << 'EOF'
# Configuration to install packages from distribution repositories during conversion
# Define packages to install (space-separated list)
MENDER_INSTALL_PACKAGES="vim htop tmux"
function install_distribution_packages_in_chroot() {
local -r dest_dir="$1"
# Update package lists
run_in_chroot_and_log_cmd "$dest_dir" "apt-get update"
# Install packages non-interactively
run_in_chroot_and_log_cmd "$dest_dir" "DEBIAN_FRONTEND=noninteractive apt-get install -y $MENDER_INSTALL_PACKAGES"
# Clean up package cache to reduce image size
run_in_chroot_and_log_cmd "$dest_dir" "apt-get clean"
run_in_chroot_and_log_cmd "$dest_dir" "rm -rf /var/lib/apt/lists/*"
}
function install_distribution_packages() {
if [ -n "$MENDER_INSTALL_PACKAGES" ]; then
log_warn "Installing packages from distribution repository: $MENDER_INSTALL_PACKAGES"
# Run package installation with proper chroot setup
run_with_chroot_setup work/rootfs install_distribution_packages_in_chroot work/rootfs
log_info "Package installation completed"
fi
}
# Add to platform modify hooks to run during the modify phase
PLATFORM_MODIFY_HOOKS+=(install_distribution_packages)
EOF
Understanding the Implementation
The configuration uses two functions:
-
install_distribution_packages_in_chroot
- Runs inside the chroot environment with:- Package list updates via
apt-get update
- Non-interactive installation with
DEBIAN_FRONTEND=noninteractive
- Cache cleanup to minimize final image size
- Package list updates via
-
install_distribution_packages
- Sets up the chroot environment usingrun_with_chroot_setup
, which handles:- Cross-architecture qemu-static setup
- DNS resolution via
/etc/resolv.conf
- Proper cleanup after execution
Running the Conversion
Include the configuration fragment during conversion. This is done through the --config
flag, of which you can have as many as you want.
An example for the Raspberry Pi 4 might be:
MENDER_ARTIFACT_NAME=release-1 ./docker-mender-convert \
--disk-image input/images/2025-05-13-raspios-bookworm-arm64-lite.img \
--config configs/raspberrypi/uboot/debian/raspberrypi4_bookworm_64bit_config \
--config input/package_install_config
Advanced Usage
Installing from Custom Repositories
Add repository configuration before package installation:
function install_distribution_packages_in_chroot() {
local -r dest_dir="$1"
# Add custom repository
echo "deb http://custom.repo/debian bookworm main" >> "$dest_dir/etc/apt/sources.list"
# Update and install
run_in_chroot_and_log_cmd "$dest_dir" "apt-get update"
run_in_chroot_and_log_cmd "$dest_dir" "DEBIAN_FRONTEND=noninteractive apt-get install -y $MENDER_INSTALL_PACKAGES"
# Cleanup
run_in_chroot_and_log_cmd "$dest_dir" "apt-get clean"
run_in_chroot_and_log_cmd "$dest_dir" "rm -rf /var/lib/apt/lists/*"
}
Conditional Package Installation
Install packages based on device type or other conditions:
function install_distribution_packages() {
case "$MENDER_DEVICE_TYPE" in
raspberrypi4*)
MENDER_INSTALL_PACKAGES="vim htop wiringpi"
;;
raspberrypi3*)
MENDER_INSTALL_PACKAGES="vim nano"
;;
esac
if [ -n "$MENDER_INSTALL_PACKAGES" ]; then
log_warn "Installing packages for $MENDER_DEVICE_TYPE: $MENDER_INSTALL_PACKAGES"
run_with_chroot_setup work/rootfs install_distribution_packages_in_chroot work/rootfs
fi
}
Troubleshooting
Common issues and solutions:
- Package not found: Ensure the package name matches the distribution’s repository
- Network errors: Docker must have internet access for package downloads
- Architecture mismatches: The chroot setup handles qemu emulation automatically
- Dependency conflicts: Use
apt-get install -f
to fix broken dependencies
Performance Considerations
- Package installation adds time to the conversion process
- Each
apt-get update
downloads package lists (~50MB for Raspberry Pi OS) - Consider creating a custom rootfs overlay for frequently used package sets
- The package cache cleanup saves ~100-200MB per conversion