# Navidrome music server # Three-stage build: UI (Node), backend (Go+taglib), runtime (Alpine) ARG CONTAINER_APP_VERSION=v0.61.1 ARG NAVIDROME_VERSION=${CONTAINER_APP_VERSION} FROM node:22-alpine AS ui-build ARG NAVIDROME_VERSION RUN apk add --no-cache git RUN git clone --depth 1 --branch ${NAVIDROME_VERSION} \ https://forge.ops.eblu.me/mirrors/navidrome.git /app WORKDIR /app/ui RUN npm ci RUN npm run build FROM golang:alpine3.22 AS build ARG NAVIDROME_VERSION RUN apk add --no-cache build-base git taglib-dev zlib-dev RUN git clone --depth 1 --branch ${NAVIDROME_VERSION} \ https://forge.ops.eblu.me/mirrors/navidrome.git /app WORKDIR /app # Copy pre-built UI assets COPY --from=ui-build /app/ui/build /app/ui/build ENV CGO_ENABLED=1 ENV CGO_CFLAGS_ALLOW="--define-prefix" RUN go build -tags=netgo \ -ldflags="-w -s -X github.com/navidrome/navidrome/consts.gitTag=${NAVIDROME_VERSION}" \ -o /navidrome . FROM alpine:3.22 ARG CONTAINER_APP_VERSION LABEL org.opencontainers.image.title="Navidrome" LABEL org.opencontainers.image.description="Navidrome is a self-hosted music server and streamer" LABEL org.opencontainers.image.version="${CONTAINER_APP_VERSION}" LABEL org.opencontainers.image.source="https://forge.eblu.me/eblume/blumeops" LABEL org.opencontainers.image.vendor="blumeops" RUN apk add --no-cache ca-certificates tzdata taglib ffmpeg \ && addgroup -g 1000 navidrome \ && adduser -u 1000 -G navidrome -D navidrome COPY --from=build /navidrome /usr/bin/navidrome EXPOSE 4533 USER 1000 CMD ["/usr/bin/navidrome"]