mirror of
https://github.com/navidrome/navidrome.git
synced 2026-04-28 03:19:38 +00:00
feat(artwork): enable native libwebp encoding in Docker image (#5350)
Some checks are pending
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Some checks are pending
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
* feat(docker): add musl build stage for native libwebp support Add a new build-alpine stage using Alpine/musl with xx cross-compilation, producing a dynamically-linked musl binary for the Docker image. The runtime image now installs libwebp, libwebpdemux, and libwebpmux and creates .so symlinks so gen2brain/webp can detect native libwebp via purego/dlopen at startup and use it automatically. The existing Debian/glibc 'build' stage is kept for standalone binary distribution (darwin, windows, and glibc linux binaries); the Docker image now ships the musl build from build-alpine instead. * fix(docker): use dynamic symlinks for libwebp libraries Avoid hardcoding SONAME versions (.so.7, .so.2, .so.3) which break on Alpine version bumps. Also fix misleading comment: the musl build is dynamic (required for purego dlopen), not static. * feat(docker): enable WebP encoding in Docker environment Signed-off-by: Deluan <deluan@navidrome.org> * fix(docker): pin build-alpine stage to Go 1.25 to match base stage Align the new build-alpine stage with the existing glibc 'base' stage, both pinned to Go 1.25. Bumping build-alpine independently would create a version skew between the Docker image binary and the standalone binaries, which should be avoided unless there is a specific reason. * fix(docker): harden build-alpine stage (musl pin, -latomic, dynamic-link check) Address review feedback on the build-alpine stage: - Pin Go builder to golang:1.25-alpine3.20 so the musl version used at build time matches the alpine:3.20 runtime image, eliminating any potential musl ABI skew between builder and runtime. - Add -extldflags '-latomic' so SQLite's 64-bit atomics resolve when cross-compiling for 32-bit arm targets (arm/v6, arm/v7). - Add a build-time check that the produced binary is dynamically linked (using 'file' from Alpine), failing the build if it is not. A fully-static binary cannot dlopen libwebp and would silently fall back to the WASM encoder, defeating the whole point of this stage. * fix(docker): revert to unpinned golang:1.25-alpine builder The golang:1.25-alpine3.20 tag suggested during review does not exist on public.ecr.aws (only 3.21, 3.22, 3.23, and unpinned 'alpine' are published). Revert to the unpinned 'golang:1.25-alpine' tag so the Docker build can resolve the base image. This means the builder's Alpine version can drift relative to the alpine:3.20 runtime, but in practice musl's backward compatibility covers this for Navidrome's small dlopen surface (a few libwebp symbols, no direct libc calls from the dlopen path). If a skew ever manifests, we can pin both builder and runtime to the same specific Alpine release in a follow-up. --------- Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
0a6b5519cc
commit
e53e60d39d
1 changed files with 50 additions and 5 deletions
55
Dockerfile
55
Dockerfile
|
|
@ -42,7 +42,46 @@ FROM scratch AS ui-bundle
|
|||
COPY --from=ui /build /build
|
||||
|
||||
########################################################################################################################
|
||||
### Build Navidrome binary
|
||||
### Build Navidrome binary for Docker image (dynamic musl, enables native libwebp via dlopen)
|
||||
FROM --platform=$BUILDPLATFORM public.ecr.aws/docker/library/golang:1.25-alpine AS build-alpine
|
||||
COPY --from=xx / /
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
RUN apk add --no-cache clang lld file git
|
||||
RUN xx-apk add --no-cache gcc musl-dev zlib-dev
|
||||
RUN xx-verify --setup
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
RUN --mount=type=bind,source=. \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
go mod download
|
||||
|
||||
ARG GIT_SHA
|
||||
ARG GIT_TAG
|
||||
|
||||
RUN --mount=type=bind,source=. \
|
||||
--mount=from=ui,source=/build,target=./ui/build,ro \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/go/pkg/mod <<EOT
|
||||
set -e
|
||||
xx-go --wrap
|
||||
export CGO_ENABLED=1
|
||||
# -latomic is required on 32-bit arm (arm/v6, arm/v7) so SQLite's 64-bit atomics resolve.
|
||||
go build -tags=netgo,sqlite_fts5 -ldflags="-w -s \
|
||||
-linkmode=external -extldflags '-latomic' \
|
||||
-X github.com/navidrome/navidrome/consts.gitSha=${GIT_SHA} \
|
||||
-X github.com/navidrome/navidrome/consts.gitTag=${GIT_TAG}" \
|
||||
-o /out/navidrome .
|
||||
# Fail the build if the binary is accidentally statically linked: dlopen (and
|
||||
# therefore native libwebp detection) only works with a dynamic interpreter.
|
||||
file /out/navidrome | grep -q "dynamically linked" || { echo "ERROR: /out/navidrome is not dynamically linked"; file /out/navidrome; exit 1; }
|
||||
EOT
|
||||
|
||||
########################################################################################################################
|
||||
### Build Navidrome binary for standalone distribution (static glibc, cross-compiled)
|
||||
FROM --platform=$BUILDPLATFORM public.ecr.aws/docker/library/golang:1.25-trixie AS base
|
||||
RUN apt-get update && apt-get install -y clang lld
|
||||
COPY --from=xx / /
|
||||
|
|
@ -104,17 +143,23 @@ FROM public.ecr.aws/docker/library/alpine:3.20 AS final
|
|||
LABEL maintainer="deluan@navidrome.org"
|
||||
LABEL org.opencontainers.image.source="https://github.com/navidrome/navidrome"
|
||||
|
||||
# Install ffmpeg and mpv
|
||||
RUN apk add -U --no-cache ffmpeg mpv sqlite
|
||||
# Install runtime dependencies
|
||||
# - libwebp + symlinks: enables native WebP encoding via purego/dlopen
|
||||
RUN apk add -U --no-cache ffmpeg mpv sqlite libwebp libwebpdemux libwebpmux && \
|
||||
for lib in libwebp libwebpdemux libwebpmux; do \
|
||||
target=$(ls /usr/lib/$lib.so.* 2>/dev/null | head -1) && \
|
||||
[ -n "$target" ] && ln -sf "$target" /usr/lib/$lib.so; \
|
||||
done
|
||||
|
||||
# Copy navidrome binary
|
||||
COPY --from=build /out/navidrome /app/
|
||||
# Copy navidrome binary (musl build for Docker, enables native libwebp)
|
||||
COPY --from=build-alpine /out/navidrome /app/
|
||||
|
||||
VOLUME ["/data", "/music"]
|
||||
ENV ND_MUSICFOLDER=/music
|
||||
ENV ND_DATAFOLDER=/data
|
||||
ENV ND_CONFIGFILE=/data/navidrome.toml
|
||||
ENV ND_PORT=4533
|
||||
ENV ND_ENABLEWEBPENCODING=true
|
||||
RUN touch /.nddockerenv
|
||||
|
||||
EXPOSE ${ND_PORT}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue