docker base image for faster builds#92
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a split Docker build (base image + SDK image) to improve build times via better layer caching, and adds GitHub Actions workflows to publish and validate multi-arch Docker images on main.
Changes:
- Add
docker/Dockerfile.sdkand refactordocker/Dockerfile.baseto be a reusable build-deps base layer. - Add workflows to publish multi-arch base/SDK images to GHCR and validate the published SDK image by building
cpp-example-collection. - Update the existing CI workflow to build using the new base+SDK Dockerfiles on pull requests.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
docker/Dockerfile.sdk |
New Dockerfile that builds & installs the SDK on top of a prebuilt base image. |
docker/Dockerfile.base |
Removes SDK build steps to make this a reusable dependency base image. |
.github/workflows/docker-images.yml |
New workflow to build/push base + SDK images and publish multi-arch manifests. |
.github/workflows/docker-validate.yml |
New workflow to validate the published SDK image after docker-images completes. |
.github/workflows/builds.yml |
Updates PR CI to build using the new base+SDK Docker image flow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| run: | | ||
| set -euo pipefail | ||
|
|
||
| if [[ "${{ github.event.before }}" == "0000000000000000000000000000000000000000" ]]; then |
There was a problem hiding this comment.
Great idea overall, my main feedback is there are a lot of new stages and scripting to achieve the result; I am spinning up on the nuances of GitHub actions and refreshing my understanding of Docker, but I am wondering if there's a simpler caching detection mechanism within Docker itself.
Will other SDKs need a similar flow for their docker image support?
There was a problem hiding this comment.
by default docker caches its build process and layers, but since the runners are publicly hosted we have no guarantee to their lifecycle/caching so we dont really get to utilize it. I do agree the scripting is a little more than i would like to split it out, but the work is relatively concise to: resolving image name/tag, ensure there was a diff on the file to trigger a build, building all architectures, then verifying the installs. If theres a better way to do it im totally game :)
WRT other SDKs: if they want to dockerize they will probably have a similar workflow. It gets hairy trying to build out a single base image used across multiple SDKs without bloating the base image. That being said im sure theres some greatest common denominator. Luckily for them other languages have a much easier time with deps than cpp so Docker hasnt been a push for them 😅
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
docker/Dockerfile.base:19
- The documented build command doesn’t pass
TARGETARCH(or explicitly enable BuildKit), but this Dockerfile relies onARG TARGETARCHlater to download the correct CMake installer. On setups where BuildKit isn’t supplyingTARGETARCH,CMAKE_ARCHcan end up empty and the build will fail. Update the instructions to either usedocker buildx build --platform ...or pass--build-arg TARGETARCH=...(and/or mention BuildKit requirement).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| case "${path}" in | ||
| docker/Dockerfile.sdk|src/*|src/*/*|include/*|include/*/*|bridge/*|bridge/*/*|client-sdk-rust/*|client-sdk-rust/*/*|cmake/*|cmake/*/*|data/*|data/*/*|CMakeLists.txt|build.sh|build.cmd|build.h.in|CMakePresets.json) | ||
| sdk_changed=true | ||
| ;; | ||
| esac |
There was a problem hiding this comment.
The change-detection glob patterns only match files up to 2 directory levels deep (e.g. src/*/*). This repo already has deeper paths (e.g. src/tests/common/...), so edits there would trigger the workflow (via paths: src/**) but sdk_changed would incorrectly remain false, preventing image rebuilds. Consider switching to a prefix/regex check (e.g. match ^src/, ^include/, etc.) or enabling globstar and using ** patterns so any depth is covered.
| case "${path}" in | |
| docker/Dockerfile.sdk|src/*|src/*/*|include/*|include/*/*|bridge/*|bridge/*/*|client-sdk-rust/*|client-sdk-rust/*/*|cmake/*|cmake/*/*|data/*|data/*/*|CMakeLists.txt|build.sh|build.cmd|build.h.in|CMakePresets.json) | |
| sdk_changed=true | |
| ;; | |
| esac | |
| if [[ "${path}" == "docker/Dockerfile.sdk" || "${path}" == "CMakeLists.txt" || "${path}" == "build.sh" || "${path}" == "build.cmd" || "${path}" == "build.h.in" || "${path}" == "CMakePresets.json" || "${path}" =~ ^(src|include|bridge|client-sdk-rust|cmake|data)/ ]]; then | |
| sdk_changed=true | |
| fi |
| # docker build -t livekit-cpp-sdk-base . -f docker/Dockerfile.base | ||
| # docker build --build-arg BASE_IMAGE=livekit-cpp-sdk-base -t livekit-cpp-sdk . -f docker/Dockerfile.sdk | ||
| # From repo root. |
There was a problem hiding this comment.
The build instructions here (and in the referenced base image build) don’t mention the TARGETARCH requirement in Dockerfile.base. On systems not using BuildKit (or where automatic build args aren’t set), building the base image with the command shown can fail when it tries to download the arch-specific CMake installer. Consider updating these instructions to use docker buildx build --platform ... or pass --build-arg TARGETARCH=... when building the base image.
| # docker build -t livekit-cpp-sdk-base . -f docker/Dockerfile.base | |
| # docker build --build-arg BASE_IMAGE=livekit-cpp-sdk-base -t livekit-cpp-sdk . -f docker/Dockerfile.sdk | |
| # From repo root. | |
| # docker build --build-arg TARGETARCH=<amd64|arm64> -t livekit-cpp-sdk-base . -f docker/Dockerfile.base | |
| # docker build --build-arg BASE_IMAGE=livekit-cpp-sdk-base -t livekit-cpp-sdk . -f docker/Dockerfile.sdk | |
| # From repo root. Alternatively, use `docker buildx build --platform linux/amd64|linux/arm64` | |
| # so `TARGETARCH` is set automatically for the base image build. |
Breakout Dockerfile into .base and .sdk docker files. They build the base and sdk respectively.