-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add optional embedding of container images (#239)
## Description <!--- Please describe what this PR is going to change --> This adds the optional capability to embed container images into hook-docker. This helps use cases where images already existing in the DinD cache is needed. Air gap envs, latency constrained/concerned envs, etc. Just FYI, with this change but without embedding any images the final 6.6 kernel initramfs is 171 MB. The v0.9.0 initramfs is 178.9 MB ## Why is this needed <!--- Link to issue you have raised --> Fixes: # ## How Has This Been Tested? <!--- Please describe in detail how you tested your changes. --> <!--- Include details of your testing environment, and the tests you ran to --> <!--- see how your change affects other areas of the code, etc. --> ## How are existing users impacted? What migration steps/scripts do we need? <!--- Fixes a bug, unblocks installation, removes a component of the stack etc --> <!--- Requires a DB migration script, etc. --> ## Checklist: I have: - [ ] updated the documentation and/or roadmap (if required) - [ ] added unit or e2e tests - [ ] provided instructions on how to upgrade
- Loading branch information
Showing
17 changed files
with
236 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
FROM golang:1.21-alpine as dev | ||
FROM golang:1.22.6-alpine AS dev | ||
COPY . /src/ | ||
WORKDIR /src | ||
RUN go mod download | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FROM scratch | ||
ENTRYPOINT [] | ||
WORKDIR / | ||
COPY ./images/ /etc/embedded-images/ | ||
# the name 001 is important as that is the order in which the scripts are executed | ||
# we need this mounting to happen before the other init.d scripts run so that | ||
# the mount points are available to them. | ||
COPY ./images-mount.sh /etc/init.d/001-images-mount.sh | ||
CMD [] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#!/bin/sh | ||
|
||
exec 3>&1 4>&2 | ||
trap 'exec 2>&4 1>&3' 0 1 2 3 | ||
exec 1>/var/log/embedded-images.log 2>&1 | ||
|
||
set -xeuo pipefail | ||
|
||
# We can't have a Linuxkit "init" container that dumps its file contents to /var and be writable | ||
# because the init process overwrites it and the contents are lost. | ||
# Instead, we have the init container, with all the Docker images, dump its contents to /etc/embedded-images. | ||
# Then we bind mount /etc/embedded-images to /run/images (/var/run is symlinked to /run) and make sure it's | ||
# read/write. This allows the DinD container to bind mount /var/run/images to /var/lib/docker and the Docker | ||
# images are available right away and /var/lib/docker is writable. | ||
mkdir -p /run/images | ||
mount -o bind,rw /etc/embedded-images/ /run/images | ||
mount -o remount,rw /run/images |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# This is an example file. It explains the required format. | ||
# For the actual file, you must remove all the comments. | ||
# The format is source image, a single space, optional additional tag of the source image, a single space, true or false to remove the original tag. | ||
#<source image> <optional additional tag of the source image> <remove original tag> | ||
# for example: | ||
quay.io/tinkerbell/tink-worker:v0.10.0 | ||
quay.io/tinkerbell/tink-worker:v0.10.0 tink-worker:v0.10.0 true | ||
quay.io/tinkerbell/actions/image2disk embedded/actions/image2disk | ||
quay.io/tinkerbell/actions/cexec 127.0.0.1/embedded/actions/cexec true |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#!/bin/bash | ||
|
||
# This script is used to build container images that are embedded in HookOS. | ||
# When HookOS boots up, the DinD container will have all the images in its cache. | ||
|
||
set -euo pipefail | ||
|
||
function docker_save_image() { | ||
local image="$1" | ||
local output_dir="$2" | ||
local output_file="${output_dir}/$(echo "${image}" | tr '/' '-')" | ||
|
||
docker save -o "${output_file}".tar "${image}" | ||
} | ||
|
||
function docker_pull_image() { | ||
local image="$1" | ||
local arch="${2-amd64}" | ||
|
||
docker pull --platform=linux/"${arch}" "${image}" | ||
} | ||
|
||
function docker_remove_image() { | ||
local image="$1" | ||
|
||
docker rmi "${image}" || true | ||
} | ||
|
||
function trap_handler() { | ||
local dind_container="$1" | ||
|
||
if [[ "${remove_dind_container}" == "true" ]]; then | ||
docker rm -f "${dind_container}" &> /dev/null | ||
else | ||
echo "DinD container NOT removed, please remove it manually" | ||
fi | ||
} | ||
|
||
function main() { | ||
local dind_container="$1" | ||
local images_file="$2" | ||
local arch="$3" | ||
local dind_container_image="$4" | ||
|
||
# Pull the images | ||
while IFS=" " read -r first_image image_tag || [ -n "${first_image}" ] ; do | ||
echo -e "----------------------- $first_image -----------------------" | ||
# Remove the image if it exists so that the image pulls the correct architecture | ||
docker_remove_image "${first_image}" | ||
docker_pull_image "${first_image}" "${arch}" | ||
done < "${images_file}" | ||
|
||
# Save the images | ||
local output_dir="${PWD}/images_tar" | ||
mkdir -p "${output_dir}" | ||
while IFS=" " read -r first_image image_tag || [ -n "${first_image}" ] ; do | ||
docker_save_image "${first_image}" "${output_dir}" | ||
done < "${images_file}" | ||
|
||
export remove_dind_container="true" | ||
# as this function maybe called multiple times, we need to ensure the container is removed | ||
trap "trap_handler ${dind_container}" RETURN | ||
# we're using set -e so the trap on RETURN will not be executed when a command fails | ||
trap "trap_handler ${dind_container}" EXIT | ||
|
||
# start DinD container | ||
# In order to avoid the src bind mount directory (./images/) ownership from changing to root | ||
# we don't bind mount to /var/lib/docker in the container because the DinD container is running as root and | ||
# will change the permissions of the bind mount directory (images/) to root. | ||
echo -e "Starting DinD container" | ||
echo -e "-----------------------" | ||
docker run -d --privileged --name "${dind_container}" -v "${PWD}/images_tar":/images_tar -v "${PWD}"/images/:/var/lib/docker-embedded/ -d "${dind_container_image}" | ||
|
||
# wait until the docker daemon is ready | ||
until docker exec "${dind_container}" docker info &> /dev/null; do | ||
sleep 1 | ||
if [[ $(docker inspect -f '{{.State.Status}}' "${dind_container}") == "exited" ]]; then | ||
echo "DinD container exited unexpectedly" | ||
docker logs "${dind_container}" | ||
exit 1 | ||
fi | ||
done | ||
|
||
# As hook-docker uses the overlay2 storage driver the DinD must use the overlay2 storage driver too. | ||
# make sure the overlay2 storage driver is used by the DinD container. | ||
# The VFS storage driver might get used if /var/lib/docker in the DinD container cannot be used by overlay2. | ||
storage_driver=$(docker exec "${dind_container}" docker info --format '{{.Driver}}') | ||
if [[ "${storage_driver}" != "overlay2" ]]; then | ||
export remove_dind_container="false" | ||
echo "DinD container is not using overlay2 storage driver, storage driver detected: ${storage_driver}" | ||
exit 1 | ||
fi | ||
|
||
# remove the contents of /var/lib/docker-embedded so that any previous images are removed. Without this it seems to cause boot issues. | ||
docker exec "${dind_container}" sh -c "rm -rf /var/lib/docker-embedded/*" | ||
|
||
# Load the images | ||
for image_file in "${output_dir}"/*; do | ||
echo -e "Loading image: ${image_file}" | ||
docker exec "${dind_container}" docker load -i "/images_tar/$(basename ${image_file})" | ||
done | ||
|
||
# clean up tar files | ||
rm -rf "${output_dir}"/* | ||
|
||
# Create any tags for the images and remove any original tags | ||
while IFS=" " read -r first_image image_tag remove_original || [ -n "${first_image}" ] ; do | ||
if [[ "${image_tag}" != "" ]]; then | ||
docker exec "${dind_container}" docker tag "${first_image}" "${image_tag}" | ||
if [[ "${remove_original}" == "true" ]]; then | ||
docker exec "${dind_container}" docker rmi "${first_image}" | ||
fi | ||
fi | ||
done < "${images_file}" | ||
|
||
# We need to copy /var/lib/docker to /var/lib/docker-embedded in order for HookOS to use the Docker images in its build. | ||
docker exec "${dind_container}" sh -c "cp -a /var/lib/docker/* /var/lib/docker-embedded/" | ||
} | ||
|
||
arch="${1-amd64}" | ||
dind_container_name="hookos-dind" | ||
images_file="images.txt" | ||
dind_container_image="${2-docker:dind}" | ||
main "${dind_container_name}" "${images_file}" "${arch}" "${dind_container_image}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters