From 695cc80f10f6431f47f62ec1805798007ef3f5c0 Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Thu, 10 Oct 2024 07:44:17 -0700 Subject: [PATCH] feat(shaka-lab-github-runner): Add support for nested containers (#63) If you want to run workflows with jobs that inside containers, you need support for nested containers. This is now possible with a little bit of configuration. To make this work, we need to synchronize a few important folders between the host and the main container so that they can be forwarded on correctly to nested containers. Part of the solution to https://github.com/shaka-project/static-ffmpeg-binaries/issues/28 --- shaka-lab-github-runner/README.md | 7 ++++ shaka-lab-github-runner/linux/start-runner.sh | 40 +++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/shaka-lab-github-runner/README.md b/shaka-lab-github-runner/README.md index 9ea8631..d49585b 100644 --- a/shaka-lab-github-runner/README.md +++ b/shaka-lab-github-runner/README.md @@ -119,6 +119,13 @@ them in text files inside `/etc/shaka-lab-github-runner.args.d/`. To add Docker command line arguments that apply to specific runner instances, add them in text files inside `/etc/shaka-lab-github-runner@$INSTANCE.args.d/`. +To support nested containers, put this in +`/etc/shaka-lab-github-runner.args.d/docker-nested`: + +``` +-v /var/run/docker.sock:/var/run/docker.sock +``` + ## Updates ```sh diff --git a/shaka-lab-github-runner/linux/start-runner.sh b/shaka-lab-github-runner/linux/start-runner.sh index 98b2a28..f6033c9 100755 --- a/shaka-lab-github-runner/linux/start-runner.sh +++ b/shaka-lab-github-runner/linux/start-runner.sh @@ -85,11 +85,46 @@ if dpkg -s shaka-lab-cert-generator &>/dev/null || \ extra_docker_args+=(--mount type=bind,src=/etc/letsencrypt,dst=/etc/letsencrypt,ro) fi +# To support nested containers in self-hosted workflows, certain folders +# expected by GitHub Actions must be consistently mapped from the outer host to +# the first container. To keep workflows ephemeral, we also wipe these before +# every run. +RUNNER_WORKDIR=/home/runner/work +MAPPED_FOLDERS=( + $RUNNER_WORKDIR + /opt/hostedtoolcache +) +for i in "${MAPPED_FOLDERS[@]}"; do + rm -rf "$i" + mkdir -p "$i" + extra_docker_args+=(--mount type=bind,src="$i",dst="$i") +done + +# This folder already exists inside the container image, but we want to keep our +# own copy of it at the host level. This will allow it to be correctly mapped +# to nested containers, and modified if necessary. +EXTERNALS=/actions-runner/externals +rm -rf "$EXTERNALS" +mkdir -p "$EXTERNALS" + +# Create a temporary docker container to extract these files. +docker pull "$DOCKER_IMAGE" +docker container create --name "$CONTAINER_NAME" "$DOCKER_IMAGE" + +# Copy "$EXTERNALS" itself from the container into the local parent of the same. +# This is because "docker cp" doesn't do wildcards, so you can't copy "e/* e/". +docker cp "$CONTAINER_NAME":"$EXTERNALS" "$EXTERNALS"/.. + +# Clean up the temporary container. +docker container rm "$CONTAINER_NAME" + +# Create a special mount for this folder. +extra_docker_args+=(--mount type=bind,src="$EXTERNALS",dst="$EXTERNALS",ro) + # Start a docker container. # --rm: Remove the container when it shuts down. # --name: The name of the container. # --network host: Use the host directly for networking, rather than NAT. -# --pull always: Always use the most up-to-date docker image. # -e ALLOCATED_PORT=...: A port number allocated to this instance. Not every # workflow needs this, but Shaka Player does. # -e RUNNER_NAME=...: The runner name, which shows up on GitHub Actions. @@ -100,10 +135,9 @@ docker run \ --rm \ --name "$CONTAINER_NAME" \ --network host \ - --pull always \ -e ALLOCATED_PORT=$(( 61700 + $INSTANCE )) \ -e RUNNER_NAME="$RUNNER_NAME" \ - -e RUNNER_WORKDIR=/tmp/runner/work \ + -e RUNNER_WORKDIR="$RUNNER_WORKDIR" \ -e DISABLE_AUTO_UPDATE=1 \ -e EPHEMERAL=1 \ "${extra_docker_args[@]}" \