Repository navigation
Open
Description
Thanks to the addition of the chisel manifest, we can now use chisel to perform multiple subsequent installations of slices on the same rootfs. This is great for creating and extending Chiseled base container images.
However, when creating or extending a Chiseled container image, the UX is not that great since you need to acquire chisel before you can create a new rootfs.
Ideally, users wouldn't have to know about chisel's dependencies or need to worry about golang versions, etc.
Providing an official Chisel container image would simplify all of this.
Current UX for acquiring Chisel
Binary
Extending a container image
FROM amd64/ubuntu:noble AS chisel
ARG BASE_IMAGE="ubuntu/dotnet-runtime"
ARG CHISEL_VERSION="v1.X.X"
# Install chisel's dependencies
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
file \
&& rm -rf /var/lib/apt/lists/*
# Install chisel
RUN chisel_url=https://github.com/canonical/chisel/releases/download/v${CHISEL_VERSION}/chisel_v${CHISEL_VERSION}_linux_amd64.tar.gz \
&& curl -fSLOJ ${chisel_url} \
&& curl -fSL ${chisel_url}.sha384 | sha384sum -c - \
&& tar -xzf chisel_v${CHISEL_VERSION}_linux_amd64.tar.gz -C /usr/bin/ chisel
# Install new slices
COPY --from=$BASE_IMAGE / /rootfs/
RUN chisel cut --release ubuntu-24.04 --root /rootfs/ \
libicu74_libs \
tzdata-legacy_zoneinfo \
tzdata_zoneinfo
FROM scratch AS final
COPY --link --from=chisel /rootfs /Golang
Extending a container image
FROM amd64/golang:1.2X AS chisel
ARG BASE_IMAGE="ubuntu/dotnet-runtime"
ARG CHISEL_VERSION="v1.X.X"
# Install chisel's dependencies
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
file \
&& rm -rf /var/lib/apt/lists/*
# Install chisel tool
RUN go install github.com/canonical/chisel/cmd/chisel@v${CHISEL_VERSION}
# Install new slices
COPY --from=$BASE_IMAGE / /rootfs/
RUN chisel cut --release ubuntu-24.04 --root /rootfs/ \
libicu74_libs \
tzdata-legacy_zoneinfo \
tzdata_zoneinfo
FROM scratch AS final
COPY --link --from=chisel /rootfs /Desired UX
Creating a base image
FROM amd64/ubuntu/chisel:v1.X.X AS chisel
# Install slices
RUN mkdir -p /rootfs \
&& chisel cut --release ubuntu-24.04 --root /rootfs \
base-files_base \
base-files_chisel \
base-files_release-info \
...
FROM scratch AS final
COPY --link --from=chisel /rootfs /Extending a base image
FROM amd64/ubuntu/chisel:v1.X.X AS chisel
ARG BASE_IMAGE="ubuntu/dotnet-runtime"
# Install new slices
COPY --from=$BASE_IMAGE / /rootfs/
RUN chisel cut --release ubuntu-24.04 --root /rootfs/ \
libicu74_libs \
tzdata-legacy_zoneinfo \
tzdata_zoneinfo
FROM scratch AS final
COPY --link --from=chisel /rootfs /Reacted by Hadrien Patte, rebornplusplus, Eddie Grau, Guillaume Fieni, zhijie-yang, mus65 and Paulus Pärssinen
Metadata
Metadata
Assignees
Labels
No labels
Activity
rebornplusplus commentedon Feb 5, 2025
This is a good point and something I have faced as well! I remember starting to work on this PR: rockcrafters/chisel-rock#1. But this work hasn't been continued for some time. I should probably find some time and pick that up again.
One question for you though, when you envision a
chiselimage, do you see it containing justchiselwithlibc6or the wholeubuntubase in the back?lbussell commentedon Feb 5, 2025
I think it would be natural for it to be as minimal as possible - just
chiseland potentiallychisel-wrapper. I don't currently see a need for any additional tools like a shell, etc. Can you think of any reasons for using a full Ubuntu base image?rebornplusplus commentedon Feb 6, 2025
Huh, good point about the
chisel-wrapper. We might need a shell if we include thechisel-wrappersince it's a shell script, but that's about it.Unless we want to run some
postinstbinary that we cannot yet do with Chisel's mutation scripts, I don't think we will need the Ubuntu base. Even if we need to execute binaries, adding another stage in the build process solves the issue.In short, no. I agree with you. It should be as minimal as possible.
polarathene commentedon Apr 26, 2025
That would specifically require
bash_bins, but also note that:FROM scratcha typicalRUNinstruction would fail as the defaultSHELLis set to/bin/sh -c. It seems only thedash_binsslice provides a/usr/bin/shsymlink to/usr/bin/dashbase-files_basefor the/bin->/usr/binsymlink (chisel-wrapperuses#! /bin/bashnot#! /usr/bin/bash).DockerfileHere's how you'd go about creating the Chisel image discussed thus far:
NOTES:
COPYcould be avoided if this gets implemented./etc/{passwd,group}it seems. Adding thebase-passwd_dataslice should remedy that AFAIK but it seems that is not presently compatible with--root /.chisel-wrappersetup / usage, so that's been omitted from theDockerfile.SHELLinstruction could be omitted if installing thedash_binsslice for/bin/shto resolve to the/usr/bin/sh->/usr/bin/dashsymlink, or alternatively creating that symlink to/usr/bin/bash? 🤷♂ (which is what Fedora does)Approx 15.6MB in weight:
ca-certificates.crtchiselUsage
If the 15.6MB excess isn't a concern you could just extend from the image (may be less wasted in a future release when you'd want the two slices):
--root /(1 stage) - Extend the officialchiselimage--root /(1 stage) - Source thechiselbinary from official imageca-certificates.crt(unless this fallback gets implemented).FROMimage).Extending an image may be simpler when it already provides
ca-certificates.crtand a shell 👍Without a shell you can use
RUNwith JSON syntax (this is not compatible withARG/ENVinstruction interpolation):--root /root-fs+COPY(2 stage)You could also still use the
/root-fs+COPYdance via a separate stage like @lbussell showed in his original proposal for creating/extending images via an officialchiselimage 👍Optimizing away the
get-chiselstageThe first stage could instead be skipped in favor of a local
COPY, but this would usually be discouraged.Dockerfilehas the source to build the Go project in this stage, containerizing the build environment into a stage is ideal.chiselfrom source may be less likely? Preferring a localCOPYsourcing a build from prior to building theDockerfilemay be simpler to maintain? 🤷♂ (personally I prefer the build environment to be self-contained within theDockerfile, as a bonus it simplifies troubleshooting / testing with users that aren't familiar with the language tooling / setup)One other option is to use the
ADDinstruction. Unfortunately that wouldn't work with remote.tar.gzassets. The archives are bundlingLICENSE+README.mdwith thechiselbinary. If it was justchiselwithout.tar.gz, you couldADDthe binary from GH releases URL directly similar toCOPY, there's a separate--checksumarg for this instruction if you wanted to verify integrity. This would likewise remove the need for the separateget-chiselstage.If using
ADDorCOPYalternatives, you may want to includeCOPY --chown=0:0to have a consistent and expected ownership forchisel. Presently the CI releases are archived with1001:128(CI runner user/group?)nilsdebruin commentedon May 9, 2025
For my projects, I have created a public docker container which can be found here:
https://hub.docker.com/r/wagtaildigital/chisel
I use it like this:
Happy to share or contribute to an official canonical based image if needed!
polarathene commentedon May 11, 2025
This is just feedback for your published image.
Dockerfileshould be public, especially for unofficial images that appear to justCOPYa binary from an unknown source.Your DockerHub page links to here for the source, but that is a 404, presumably it's a private repo?
Is there a reason
APP_REPOdefaults to yourchiselfork? (I assume it's for theAPP_BRANCHwhich would be redundant once this PR is merged?)Defaults should be stable/predictable to upstream, those build ARG defaults you have currently make it a little less convenient to use without providing explicit overrides to prefer upstream sources (assuming the
Dockerfilewould be public).Without seeing the
Dockerfile, the DockerHub docs are a bit vague on whatAPP_VERSIONis for sinceAPP_REPO+APP_BRANCHimply source selection already 😅wagtaildigital/chisel:v1.1.0seems to be aDockerfilethat just copies in an external build/download from somewhere?:Small tip, usually it's a more common convention for the semver tag to exclude the
vprefix when it's an image tag. While with git tags it's more common to have thevprefix, and I think with Go projects even expected.I don't really get the purpose of a
:v1.1.0-latesttag? I'm assuming you have a GHA managing that, but slightly misconfigured that it appended-latest?For comparison, you also have a
latest-hardenedtag (but justhardenedwould suffice? Assuming it's handled as a suffix via GHA, I can see how a suffix would be simpler to configure).You are publishing tags with timestamps and digests?? (
v1.1.0-20250511-d13e667d6273531e92f641803b8a98f151b0bd0f-hardened)There should be no need for that. You can pin an image by it's digest, otherwise update the respective tags as needed.