Skip to content

Commit

Permalink
Overhaul, generalize containerized build scripts
Browse files Browse the repository at this point in the history
Accept command-line arguments and environment variables to specify:
- BUILDROOT: the default source of config, hostid and zpool.cache files
- ZBMCONF: a specific configuration file to use inside the container
- ZBMOUTPUT: a directory where build artifacts will be copied
- HOSTID: a specific hostid file to be copied to /etc/hostid
- POOLCACHE: a specific cache to be copied to /etc/zfs/zpool.cache
- ZBMTAG: a tag to fetch if /zbm is not pre-populated in container

The zbm-build.sh script now overrides ImageDir values and removes
Global.BootMountPoint from any configuration, writing artifacts to a
temporary directory and copying them to the output directory after a
successful run.

When /zbm is not pre-populated, it is now built in-container from a
tarball fetched from github.com rather than a git clone. This reduces
instantiation time and lightens the dependency burden.

Closes: #195.
  • Loading branch information
ahesford committed Aug 4, 2021
1 parent cfa0455 commit 83b1766
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 81 deletions.
9 changes: 8 additions & 1 deletion contrib/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ RUN echo "ignorepkg=linux" > /etc/xbps.d/10-nolinux.conf \

# Install components necessary to build the image
RUN xbps-query -Rp run_depends zfsbootmenu | xargs xbps-install -y
RUN xbps-install -y linux5.10 linux5.10-headers zfs gummiboot-efistub
RUN xbps-install -y linux5.10 linux5.10-headers \
zfs gummiboot-efistub curl yq-go bash

# Remove headers and massive dkms development toolchain; binutils
# provides objcopy, which is necessary for UEFI bundle creation
RUN xbps-pkgdb -m manual binutils
RUN echo "ignorepkg=dkms" > /etc/xbps.d/10-nodkms.conf
RUN xbps-remove -Roy linux5.10-headers dkms && rm -f /var/cache/xbps/*

# Record a commit hash if one was provided
RUN if [ -n "${ZBM_COMMIT_HASH}" ]; then echo "${ZBM_COMMIT_HASH}" > /etc/zbm-commit-hash; fi
Expand Down
109 changes: 80 additions & 29 deletions contrib/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,33 +50,73 @@ components of the ZFSBootMenu repository:

- `90zfsbootmenu`, the Dracut module encapsulating ZFSBootMenu functionality;
- `bin/generate-zbm`, the executable script that creates ZFSBootMenu images;
- `contrib/docker`, providing either `config.yaml` or `config.yaml.default`.

If the build script finds the volume mounted at `/zbm` empty, it will install
the `git` package and clone the master branch of the upstream ZFSBootMenu
repository. This makes the image capable of producing default images without
needing a local clone of the repository. To build anything but the head commit
of the upstream master branch, clone the repository, checkout an aribtrary
commit or make local changes, and mount that repository at `/zbm`.

## Contents of `contrib/docker`

The build script expects to find a valid ZFSBootMenu configuration file at
`/zbm/contrib/docker/config.yaml` within the container. If this file does not
exist, the file `/zbm/contrib/docker/config.yaml.default` will be copied to the
expected location. At least one of these files must exist or the build script
will fail. The default configuration will store images in the directory
`contrib/docker/build`, which will be created by `generate-zbm` if it does not
already exist.

Builder containers do not have access to local files `/etc/zfs/zpool.cache` or
`/etc/hostid`. If one or both of these components are desired in the output
image (for example, to ensure consistency with the build host), copy the
desired files to `contrib/docker/zpool.cache` or `contrib/docker/hostid`,
respectively. If the build script finds these files, it will copy them into the
container where the ZFSBootMenu Dracut module expects to find them. If one of
these files is missing, any corresponding file already installed in the
container will be *removed*.

If the build script finds the volume mounted at `/zbm` empty, it will fetch an
archive of the official ZFSBootMenu repository on github.com. This makes the
image capable of producing default images without needing a local clone of the
repository. The specific commit, tag or branch to fetch can be specified at
container run time.

## Command-Line Arguments and Environment Variables

The build script accepts several command-line arguments or environment
variables that override its default behavior. Run the container with the `-h`
command-line argument to see a summary of build options and their default
options. The options are:

- `$BUILDROOT` specifies a default root for image builds. The build root is
expected to hold a default default configuration file and output directory,
as well as optional hostid and pool cache files. If an output directory,
specific configuration and (when appropriate) hostid or pool cache are
specified, then `$BUILDROOT` is not relevant.

The environment variable or default can be overridden with the `-b` option.

- `$ZBMCONF` specifies the in-container path to a specific configuration file.
The build script will override any `ImageDir` paths and remove any
`Global.BootMountPoint` option but otherwise uses the configuration as-is.A

The environment variable or default can be overridded with the `-c` option.

- `$ZBMOUTPUT` specifies the in-container path to an output directory. As noted
above, the build script overrides any `ImageDir` path in a configuration,
pointing it instead to a temporary output directory. After the script
successfully runs `generate-zbm`, it will copy any artifacts from the
temporary build directory to `$ZBMOUTPUT`.

The environment variable or default can be overridded with the `-o` option.

- `$HOSTID` specifies the in-container path to a hostid file. If this file is
specified, it will be copied to `/etc/hostid` inside the container for
inclusion in ZFSBootMenu images. If not, any `/etc/hostid` in the container
will be removed. (Note: unless the `zfsbootmenu` dracut module is configured
with `release_mode=1`, the module may still create an `/etc/hostid` with
potentially arbitrary contents in output images.

The environment variable or default can be overridded with the `-H` option.

- `$POOLCACHE` specifies the in-container path to a ZFS pool cache file. If
this file is specified, it will be copied to `/etc/zfs/zpool.cache` inside
the container for inclusion in ZFSBootMenu images. If not, any
`/etc/zfs/zpool.cache` in the container will be removed.

The environment variable or default can be overridded with the `-C` option.

- `$ZBMTAG` specifies any "commit-ish" label recognized by `git` as a pointer
to a specific git commit. This can be a branch name (to grab the head of that
branch), tag or commit hash. If `/zbm` in the container is not pre-populated,
the container will fetch and unpack the named tag. By default, the value of
`$ZBMTAG` will be taken from the contents of `/etc/zbm-commit-hash` if the
container was built with the `ZBM_COMMIT_HASH` build argument; otherwise, the
default is `master`. The tag is ignored if `/zbm` in the container is not
empty.

The environment variable or default can be overridded with the `-t` option.

An additional command-line argument, `-e`, allows the ZFSBootMenu configuration
to be modified with `yq-go eval` statements at container run time. Do not use
this unless you review the build script and understand, without documentation,
what will happen!

## Build Examples

Expand All @@ -85,7 +125,7 @@ default configuration using a local ZFSBootMenu repository `/sw/zfsbootmenu`,
simply run

```sh
podman run -v /sw/zfsbootmenu:/zbm /zbm
podman run -v /sw/zfsbootmenu:/zbm zbm
```

After some console output, the container should terminate and the directory
Expand All @@ -101,7 +141,18 @@ directory:

```sh
cp /etc/hostid /sw/zfsbootmenu/contrib/docker/hostid
podman run -v /sw/zfsbootmenu:/zbm /zbm
podman run -v /sw/zfsbootmenu:/zbm zbm
```

To create an image from the current `master` branch without having a local
repository, store the output images in `/boot/efi/EFI/zfsbootmenu` and include
the hostid of the current system, assuming a `zbm` builder container is tagged
locally:

```sh
mkdir -p /boot/efi/EFI/zfsbootmenu
podman run -v /boot/efi/EFI/zfsbootmenu:/output \
-v /etc/hostid:/hostid:ro zbm -o /output -H /hostid
```

# Using Docker Compose
Expand Down
4 changes: 2 additions & 2 deletions contrib/docker/config.yaml.default
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ Global:
# Make sure to look for dracut configuration in the repo
DracutConfDir: /zbm/etc/zfsbootmenu/dracut.conf.d
Components:
# Dump kernel/initramfs components in the tree;
# generate-zbm creates this directory if necessary
# zbm-build.sh overwrites this anyway
ImageDir: /zbm/contrib/docker/build
Enabled: true
# Disable versioning, this is usually a one-off creation
Versions: false
syslinux:
Enabled: false
EFI:
# zbm-build.sh overwrites this anyway
ImageDir: /zbm/contrib/docker/build
Versions: false
Enabled: true
Expand Down

0 comments on commit 83b1766

Please sign in to comment.