Skip to content

Commit 46b0bac

Browse files
committed
container: Add export --format=tar command
Some people want to use container build tools, but for compatibility with older systems export a tar format of the OS state e.g. Anaconda liveimg expects this. Basically this is only *slightly* more than just `tar cf`; we need to handle SELinux labeling and move the kernel. Ref: #1957 Assisted-by: OpenCode (Sonnet 4.5) Signed-off-by: Colin Walters <walters@verbum.org>
1 parent 51dabaa commit 46b0bac

File tree

9 files changed

+690
-1
lines changed

9 files changed

+690
-1
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ test-tmt *ARGS: build
101101
[group('core')]
102102
test-container: build build-units
103103
podman run --rm --read-only localhost/bootc-units /usr/bin/bootc-units
104-
podman run --rm --env=BOOTC_variant={{variant}} --env=BOOTC_base={{base}} {{base_img}} bootc-integration-tests container
104+
podman run --rm --env=BOOTC_variant={{variant}} --env=BOOTC_base={{base}} --mount=type=image,source={{base_img}},target=/run/target {{base_img}} bootc-integration-tests container
105105

106106
# Build and test sealed composefs images
107107
[group('core')]

crates/lib/src/cli.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,40 @@ pub(crate) enum ContainerOpts {
415415
#[clap(last = true)]
416416
args: Vec<OsString>,
417417
},
418+
/// Export container filesystem as a tar archive.
419+
///
420+
/// This command exports the container filesystem in a bootable format with proper
421+
/// SELinux labeling. The output is written to stdout by default or to a specified file.
422+
///
423+
/// Example:
424+
/// bootc container export /target > output.tar
425+
Export {
426+
/// Format for export output
427+
#[clap(long, default_value = "tar")]
428+
format: ExportFormat,
429+
430+
/// Output file (defaults to stdout)
431+
#[clap(long, short = 'o')]
432+
output: Option<Utf8PathBuf>,
433+
434+
/// Copy kernel and initramfs from /usr/lib/modules to /boot for legacy compatibility.
435+
/// This is useful for installers that expect the kernel in /boot.
436+
#[clap(long)]
437+
kernel_in_boot: bool,
438+
439+
/// Disable SELinux labeling in the exported archive.
440+
#[clap(long)]
441+
disable_selinux: bool,
442+
443+
/// Path to the container filesystem root
444+
target: Utf8PathBuf,
445+
},
446+
}
447+
448+
#[derive(Debug, Clone, ValueEnum, PartialEq, Eq)]
449+
pub(crate) enum ExportFormat {
450+
/// Export as tar archive
451+
Tar,
418452
}
419453

420454
/// Subcommands which operate on images.
@@ -1626,6 +1660,22 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
16261660
kargs,
16271661
args,
16281662
} => crate::ukify::build_ukify(&rootfs, &kargs, &args),
1663+
ContainerOpts::Export {
1664+
format,
1665+
target,
1666+
output,
1667+
kernel_in_boot,
1668+
disable_selinux,
1669+
} => {
1670+
crate::container_export::export(
1671+
&format,
1672+
&target,
1673+
output.as_deref(),
1674+
kernel_in_boot,
1675+
disable_selinux,
1676+
)
1677+
.await
1678+
}
16291679
},
16301680
Opt::Completion { shell } => {
16311681
use clap_complete::aot::generate;

0 commit comments

Comments
 (0)