Skip to content

Commit 807483f

Browse files
committed
install: Optionally use host mounted /var/lib/containers
I just keep hitting the host skopeo requirement in corner cases; it's annoying because *otherwise* the container is self-sufficient. Change our installation instructions to add a `/var/lib/containers` bind mount. For the time being of course we continue to support forking off `skopeo` on the host. One thing I still want to investigate is dropping some requirements here and switch to *dynamically* setting up the mount points inside the container as is mentioned in https://brauner.io/2023/02/28/mounting-into-mount-namespaces.html but this currently requires relatively new host kernels. As far as test coverage, this changes the Github Action that uses ubuntu and needed to build a newer skopeo to stop doing that, and in fact we explicitly *remove* skopeo to verify it's not being used in the install process. I didn't change the other install tests to verify they keep working. Closes: #81 Signed-off-by: Colin Walters <[email protected]>
1 parent cbe6062 commit 807483f

File tree

4 files changed

+50
-42
lines changed

4 files changed

+50
-42
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -116,39 +116,13 @@ jobs:
116116
run: sudo tar -C / -xvf bootc.tar.zst
117117
- name: Integration tests
118118
run: bootc internal-tests run-container-integration
119-
build-skopeo-ubuntu:
120-
name: "Build skopeo git main for ubuntu"
121-
runs-on: ubuntu-latest
122-
steps:
123-
- uses: actions/checkout@v3
124-
with:
125-
repository: containers/skopeo
126-
path: skopeo
127-
- name: Install build deps
128-
run: |
129-
sudo sed -ie s,'# deb-src,deb-src,' /etc/apt/sources.list
130-
sudo apt update
131-
sudo apt build-dep -y skopeo
132-
- uses: actions/setup-go@v4
133-
with:
134-
go-version: '>=1.20'
135-
- name: Build skopeo
136-
run: cd skopeo && make bin/skopeo PREFIX=/usr
137-
- name: Upload binary
138-
uses: actions/upload-artifact@v4
139-
with:
140-
name: skopeo-ubuntu
141-
path: skopeo/bin/skopeo
142119
privtest-alongside:
143120
name: "Test install-alongside"
144-
needs: [build-fedora, build-skopeo-ubuntu]
121+
needs: [build-fedora]
145122
runs-on: ubuntu-latest
146123
steps:
147-
- name: Download
148-
uses: actions/download-artifact@v4
149-
with:
150-
name: skopeo-ubuntu
151-
- run: chmod a+x skopeo && sudo mv skopeo /usr/bin
124+
- name: Ensure host skopeo is disabled
125+
run: sudo rm -f /bin/skopeo /usr/bin/skopeo
152126
- name: Download
153127
uses: actions/download-artifact@v3
154128
with:
@@ -158,7 +132,7 @@ jobs:
158132
- name: Integration tests
159133
run: |
160134
set -xeuo pipefail
161-
sudo podman run --rm -ti --privileged -v /:/target -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
135+
sudo podman run --rm -ti --privileged --env RUST_LOG=debug -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
162136
quay.io/centos-bootc/fedora-bootc-dev:eln bootc install to-filesystem \
163137
--karg=foo=bar --disable-selinux --replace=alongside /target
164138
ls -al /boot/loader/

docs/install.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ inside the container.
2727
There are two sub-commands: `bootc install to-disk` and `boot install to-filesystem`.
2828

2929
However, nothing *else* (external) is required to perform a basic installation
30-
to disk. (The one exception to host requirements today is that the host must
31-
have `skopeo` installed. This is a bug; more information in
32-
[this issue](https://github.com/containers/bootc/issues/81).)
30+
to disk - the container image itself comes with a baseline self-sufficient installer
31+
that sets things up ready to boot.
3332

3433
This is motivated by experience gained from the Fedora CoreOS
3534
project where today the expectation is that one boots from a pre-existing disk
@@ -58,7 +57,7 @@ to an existing system and install your container image. Failure to run
5857
Here's an example of using `bootc install` (root/elevated permission required):
5958

6059
```bash
61-
podman run --rm --privileged --pid=host --security-opt label=type:unconfined_t <image> bootc install to-disk /path/to/disk
60+
podman run --rm --privileged --pid=host -v /var/lib/containers:/var/lib/containers --security-opt label=type:unconfined_t <image> bootc install to-disk /path/to/disk
6261
```
6362

6463
Note that while `--privileged` is used, this command will not perform any
@@ -70,6 +69,10 @@ The `--pid=host --security-opt label=type:unconfined_t` today
7069
make it more convenient for bootc to perform some privileged
7170
operations; in the future these requirement may be dropped.
7271

72+
The `-v /var/lib/containers:/var/lib/containers` option is required in order
73+
for the container to access its own underlying image, which is used by
74+
the installation process.
75+
7376
Jump to the section for [`install to-filesystem`](#more-advanced-installation) later
7477
in this document for additional information about that method.
7578

@@ -219,7 +222,7 @@ via e.g.:
219222

220223
```bash
221224
truncate -s 10G exampleos.raw
222-
podman run --rm --privileged --pid=host --security-opt label=type:unconfined_t -v .:/output <yourimage> bootc install to-disk --generic-image --via-loopback /output/myimage.raw
225+
podman run --rm --privileged --pid=host --security-opt label=type:unconfined_t -v /var/lib/containers:/var/lib/containers -v .:/output <yourimage> bootc install to-disk --generic-image --via-loopback /output/myimage.raw
223226
```
224227

225228
Notice that we use `--generic-image` for this use case.
@@ -237,7 +240,7 @@ support the root storage setup already initialized.
237240
The core command should look like this (root/elevated permission required):
238241

239242
```bash
240-
podman run --rm --privileged -v /:/target \
243+
podman run --rm --privileged -v /var/lib/containers:/var/lib/containers -v /:/target \
241244
--pid=host --security-opt label=type:unconfined_t \
242245
<image> \
243246
bootc install to-filesystem --replace=alongside /target

lib/src/install.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ pub(crate) struct SourceInfo {
245245
pub(crate) selinux: bool,
246246
/// Whether the source is available in the host mount namespace
247247
pub(crate) in_host_mountns: bool,
248+
/// Whether we were invoked with -v /var/lib/containers:/var/lib/containers
249+
pub(crate) have_host_container_storage: bool,
248250
}
249251

250252
// Shared read-only global state
@@ -387,23 +389,41 @@ impl SourceInfo {
387389
};
388390
let digest = crate::podman::imageid_to_digest(&container_info.imageid)?;
389391

392+
let root = Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
393+
let have_host_container_storage = Utf8Path::new(crate::podman::CONTAINER_STORAGE)
394+
.try_exists()?
395+
&& ostree_ext::mountutil::is_mountpoint(
396+
&root,
397+
crate::podman::CONTAINER_STORAGE.trim_start_matches('/'),
398+
)?
399+
.unwrap_or_default();
400+
390401
// Verify up front we can do the fetch
391-
require_skopeo_with_containers_storage()?;
402+
if have_host_container_storage {
403+
tracing::debug!("Host container storage found");
404+
} else {
405+
tracing::debug!(
406+
"No {} mount available, checking skopeo",
407+
crate::podman::CONTAINER_STORAGE
408+
);
409+
require_skopeo_with_containers_storage()?;
410+
}
392411

393-
Self::new(imageref, Some(digest), true)
412+
Self::new(imageref, Some(digest), true, have_host_container_storage)
394413
}
395414

396415
#[context("Creating source info from a given imageref")]
397416
pub(crate) fn from_imageref(imageref: &str) -> Result<Self> {
398417
let imageref = ostree_container::ImageReference::try_from(imageref)?;
399-
Self::new(imageref, None, false)
418+
Self::new(imageref, None, false, false)
400419
}
401420

402421
/// Construct a new source information structure
403422
fn new(
404423
imageref: ostree_container::ImageReference,
405424
digest: Option<String>,
406425
in_host_mountns: bool,
426+
have_host_container_storage: bool,
407427
) -> Result<Self> {
408428
let cancellable = ostree::gio::Cancellable::NONE;
409429
let commit = Task::new("Reading ostree commit", "ostree")
@@ -424,6 +444,7 @@ impl SourceInfo {
424444
digest,
425445
selinux,
426446
in_host_mountns,
447+
have_host_container_storage,
427448
})
428449
}
429450
}
@@ -630,10 +651,16 @@ async fn initialize_ostree_root_from_self(
630651
}
631652
};
632653

633-
// We need to fetch the container image from the root mount namespace
634-
let skopeo_cmd = run_in_host_mountns("skopeo");
654+
// We need to fetch the container image from the root mount namespace. If
655+
// we don't have /var/lib/containers mounted in this image, fork off skopeo
656+
// in the host mountnfs.
657+
let skopeo_cmd = if !state.source.have_host_container_storage {
658+
Some(run_in_host_mountns("skopeo"))
659+
} else {
660+
None
661+
};
635662
let proxy_cfg = ostree_container::store::ImageProxyConfig {
636-
skopeo_cmd: Some(skopeo_cmd),
663+
skopeo_cmd,
637664
..Default::default()
638665
};
639666

lib/src/podman.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ use serde::Deserialize;
44
use crate::install::run_in_host_mountns;
55
use crate::task::Task;
66

7+
/// Where we look inside our container to find our own image
8+
/// for use with `bootc install`.
9+
pub(crate) const CONTAINER_STORAGE: &str = "/var/lib/containers";
10+
711
#[derive(Deserialize)]
812
#[serde(rename_all = "PascalCase")]
913
pub(crate) struct Inspect {

0 commit comments

Comments
 (0)