From 4dd1cbc8038dd3e005c5fca982a57c3f12aa417d Mon Sep 17 00:00:00 2001 From: Tom Foster Date: Sun, 7 Sep 2025 13:21:58 +0100 Subject: [PATCH] fix(docker): Resolve liburing.so.2 loading error for non-root users Container failed to start when running as non-root (user 1000:1000) because copied directories had restrictive 770 permissions, likely due to different umask in persistent BuildKit. Non-root users couldn't access /usr/lib to load required dynamic libraries. Introduces prepper stage using Ubuntu to organize files into layered structure with explicit 755 directory permissions before copying to scratch image. Also fixes workflow syntax error and removes docker/** from paths-ignore to ensure Docker changes trigger CI builds. --- .forgejo/workflows/release-image.yml | 4 +- docker/Dockerfile | 55 +++++++++++++++++++--------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/.forgejo/workflows/release-image.yml b/.forgejo/workflows/release-image.yml index 7b29b7ca..834b5602 100644 --- a/.forgejo/workflows/release-image.yml +++ b/.forgejo/workflows/release-image.yml @@ -11,7 +11,6 @@ on: - ".gitignore" - "renovate.json" - "pkg/**" - - "docker/**" - "docs/**" push: branches: @@ -23,7 +22,6 @@ on: - ".gitignore" - "renovate.json" - "pkg/**" - - "docker/**" - "docs/**" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -199,7 +197,7 @@ jobs: context: . file: "docker/Dockerfile" build-args: | - GIT_COMMIT_HASH=${{ github.sha }}) + GIT_COMMIT_HASH=${{ github.sha }} GIT_COMMIT_HASH_SHORT=${{ env.COMMIT_SHORT_SHA }} GIT_REMOTE_URL=${{github.event.repository.html_url }} GIT_REMOTE_COMMIT_URL=${{github.event.head_commit.url }} diff --git a/docker/Dockerfile b/docker/Dockerfile index 55150902..669a995a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -199,32 +199,53 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \ EOF # Extract dynamically linked dependencies -RUN </dev/null) && [ -n "$lddtree_output" ]; then + echo "$lddtree_output" | awk '{print $(NF-0) " " $1}' | sort -u -k 1,1 | \ + awk '{dest = ($2 ~ /^\//) ? "/out/libs-root" $2 : "/out/libs/" $2; print "install -D " $1 " " dest}' | \ + while read cmd; do eval "$cmd"; done + fi done -EOF + + # Show what will be copied to runtime + echo "=== Libraries being copied to runtime image:" + find /out/libs* -type f 2>/dev/null | sort || echo "No libraries found" +DEPS_EOF + +FROM ubuntu:latest AS prepper + +# Create layer structure +RUN mkdir -p /layer1/etc/ssl/certs /layer1/usr/lib \ + /layer2/sbin /layer2/sbom + +# Copy SSL certs to layer1 +COPY --from=base /etc/ssl/certs /layer1/etc/ssl/certs + +# Copy libraries to layer1 +COPY --from=builder /out/libs-root/ /layer1/ +COPY --from=builder /out/libs/ /layer1/usr/lib/ + +# Copy binaries and SBOM to layer2 +COPY --from=builder /out/sbin/ /layer2/sbin/ +COPY --from=builder /out/sbom/ /layer2/sbom/ + +# Fix permissions after copying +RUN chmod -R 755 /layer1 /layer2 FROM scratch WORKDIR / -# Copy root certs for tls into image -# You can also mount the certs from the host -# --volume /etc/ssl/certs:/etc/ssl/certs:ro -COPY --from=base /etc/ssl/certs /etc/ssl/certs +# Copy stable layer (libraries, certs) +COPY --from=prepper /layer1/ / -# Copy our build -COPY --from=builder /out/sbin/ /sbin/ -# Copy SBOM -COPY --from=builder /out/sbom/ /sbom/ - -# Copy dynamic libraries to root -COPY --from=builder /out/libs-root/ / -COPY --from=builder /out/libs/ /usr/lib/ +# Copy volatile layer (binaries, SBOM) +COPY --from=prepper /layer2/ / # Inform linker where to find libraries ENV LD_LIBRARY_PATH=/usr/lib