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.
This commit is contained in:
Tom Foster 2025-09-07 13:21:58 +01:00
commit 4dd1cbc803
2 changed files with 39 additions and 20 deletions

View file

@ -11,7 +11,6 @@ on:
- ".gitignore" - ".gitignore"
- "renovate.json" - "renovate.json"
- "pkg/**" - "pkg/**"
- "docker/**"
- "docs/**" - "docs/**"
push: push:
branches: branches:
@ -23,7 +22,6 @@ on:
- ".gitignore" - ".gitignore"
- "renovate.json" - "renovate.json"
- "pkg/**" - "pkg/**"
- "docker/**"
- "docs/**" - "docs/**"
# Allows you to run this workflow manually from the Actions tab # Allows you to run this workflow manually from the Actions tab
workflow_dispatch: workflow_dispatch:
@ -199,7 +197,7 @@ jobs:
context: . context: .
file: "docker/Dockerfile" file: "docker/Dockerfile"
build-args: | build-args: |
GIT_COMMIT_HASH=${{ github.sha }}) GIT_COMMIT_HASH=${{ github.sha }}
GIT_COMMIT_HASH_SHORT=${{ env.COMMIT_SHORT_SHA }} GIT_COMMIT_HASH_SHORT=${{ env.COMMIT_SHORT_SHA }}
GIT_REMOTE_URL=${{github.event.repository.html_url }} GIT_REMOTE_URL=${{github.event.repository.html_url }}
GIT_REMOTE_COMMIT_URL=${{github.event.head_commit.url }} GIT_REMOTE_COMMIT_URL=${{github.event.head_commit.url }}

View file

@ -199,32 +199,53 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
EOF EOF
# Extract dynamically linked dependencies # Extract dynamically linked dependencies
RUN <<EOF RUN <<'DEPS_EOF'
set -o xtrace set -o xtrace
mkdir /out/libs mkdir /out/libs /out/libs-root
mkdir /out/libs-root
# Process each binary
for BINARY in /out/sbin/*; do for BINARY in /out/sbin/*; do
lddtree "$BINARY" | awk '{print $(NF-0) " " $1}' | sort -u -k 1,1 | awk '{print "install", "-D", $1, (($2 ~ /^\//) ? "/out/libs-root" $2 : "/out/libs/" $2)}' | xargs -I {} sh -c {} if lddtree_output=$(lddtree "$BINARY" 2>/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 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 FROM scratch
WORKDIR / WORKDIR /
# Copy root certs for tls into image # Copy stable layer (libraries, certs)
# You can also mount the certs from the host COPY --from=prepper /layer1/ /
# --volume /etc/ssl/certs:/etc/ssl/certs:ro
COPY --from=base /etc/ssl/certs /etc/ssl/certs
# Copy our build # Copy volatile layer (binaries, SBOM)
COPY --from=builder /out/sbin/ /sbin/ COPY --from=prepper /layer2/ /
# 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/
# Inform linker where to find libraries # Inform linker where to find libraries
ENV LD_LIBRARY_PATH=/usr/lib ENV LD_LIBRARY_PATH=/usr/lib