diff --git a/argocd/manifests/navidrome/deployment.yaml b/argocd/manifests/navidrome/deployment.yaml index 978e69c..3e81b14 100644 --- a/argocd/manifests/navidrome/deployment.yaml +++ b/argocd/manifests/navidrome/deployment.yaml @@ -16,7 +16,7 @@ spec: spec: containers: - name: navidrome - image: deluan/navidrome:0.60.3 + image: registry.ops.eblu.me/blumeops/navidrome:v1.0.0 ports: - containerPort: 4533 name: http diff --git a/containers/navidrome/Dockerfile b/containers/navidrome/Dockerfile new file mode 100644 index 0000000..a314143 --- /dev/null +++ b/containers/navidrome/Dockerfile @@ -0,0 +1,51 @@ +# Navidrome music server +# Three-stage build: UI (Node), backend (Go+taglib), runtime (Alpine) + +ARG NAVIDROME_VERSION=v0.60.3 + +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://github.com/navidrome/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 + +RUN git clone --depth 1 --branch ${NAVIDROME_VERSION} \ + https://github.com/navidrome/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 + +LABEL org.opencontainers.image.title=Navidrome +LABEL org.opencontainers.image.description="Navidrome is a self-hosted music server and streamer" +LABEL org.opencontainers.image.source=https://github.com/navidrome/navidrome + +RUN apk add --no-cache ca-certificates tzdata taglib ffmpeg + +COPY --from=build /navidrome /usr/bin/navidrome + +EXPOSE 4533 + +USER 65534 +CMD ["/usr/bin/navidrome"] diff --git a/docs/changelog.d/feature-document-container-build-port-navidrome.feature.md b/docs/changelog.d/feature-document-container-build-port-navidrome.feature.md new file mode 100644 index 0000000..cae7e5b --- /dev/null +++ b/docs/changelog.d/feature-document-container-build-port-navidrome.feature.md @@ -0,0 +1 @@ +Add how-to guide for building container images and port navidrome to a custom-built container image. diff --git a/docs/how-to/build-container-image.md b/docs/how-to/build-container-image.md new file mode 100644 index 0000000..3086b23 --- /dev/null +++ b/docs/how-to/build-container-image.md @@ -0,0 +1,104 @@ +--- +title: Build Container Image +modified: 2026-02-15 +last-reviewed: 2026-02-15 +tags: + - how-to + - containers + - ci +--- + +# Build a Container Image + +How to create a custom container image in BlumeOps, build it locally, and release it to the [[zot]] registry via the Forgejo CI pipeline. + +## Prerequisites + +- [Dagger CLI](https://docs.dagger.io/install) installed locally +- A Dockerfile for the service you want to build + +## 1. Create the container directory + +Add a `Dockerfile` (and any supporting files) under `containers//`: + +``` +containers// +├── Dockerfile +└── (optional scripts, configs) +``` + +The directory name becomes the image name: `registry.ops.eblu.me/blumeops/`. + +## 2. Build locally + +Test your image with Dagger: + +```bash +dagger call build --src=. --container-name= +``` + +This builds `containers//Dockerfile` using the Dagger `docker_build()` function. Fix any build errors before proceeding. + +## 3. Release + +Once the image builds cleanly, create a tagged release: + +```bash +mise run container-tag-and-release v1.0.0 +``` + +This creates a git tag `-v1.0.0` and pushes it. The `build-container` Forgejo workflow triggers on the tag, builds the image via Dagger, and publishes it to the registry as `registry.ops.eblu.me/blumeops/:v1.0.0`. + +Check available images and tags with: + +```bash +mise run container-list +``` + +## 4. Update k8s manifests + +Change the image reference in `argocd/manifests//deployment.yaml`: + +```yaml +image: registry.ops.eblu.me/blumeops/:v1.0.0 +``` + +Then deploy per [[deploy-k8s-service]]. + +## Common Patterns + +Existing containers demonstrate several build approaches: + +| Pattern | Example | Notes | +|---------|---------|-------| +| Alpine package install | [[#transmission]] | Simplest — install from apk | +| Go from source | [[#miniflux]] | Clone upstream, `go build` | +| Multi-stage with Node + Go | [[#navidrome]] | Separate UI and backend build stages | +| Multi-stage Elixir | [[#teslamate]] | Elixir release with Node assets | +| Runtime tarball download | [[#kiwix-serve]] | Download pre-built binary with arch detection | + +### transmission + +`containers/transmission/Dockerfile` — Installs transmission-daemon directly from Alpine packages. Good starting point for services available in apk. + +### miniflux + +`containers/miniflux/Dockerfile` — Two-stage Go build. Clones upstream at a pinned version tag, runs `make`, copies the binary into a minimal Alpine runtime. + +### navidrome + +`containers/navidrome/Dockerfile` — Three-stage build with separate Node.js UI compilation, Go backend build with CGO (taglib), and a minimal Alpine runtime with ffmpeg. + +### teslamate + +`containers/teslamate/Dockerfile` — Two-stage Elixir build with Node.js asset compilation. Uses Debian-based images due to Elixir/OTP dependencies. + +### kiwix-serve + +`containers/kiwix-serve/Dockerfile` — Downloads a pre-built binary from upstream, with architecture detection for cross-platform support. + +## Related + +- [[deploy-k8s-service]] — Deploying the service that uses the image +- [[create-release-artifact-workflow]] — Alternative: release non-container artifacts +- [[dagger]] — Dagger CI reference diff --git a/docs/how-to/how-to.md b/docs/how-to/how-to.md index ba8f327..7d8a524 100644 --- a/docs/how-to/how-to.md +++ b/docs/how-to/how-to.md @@ -16,6 +16,7 @@ Task-oriented instructions for common BlumeOps operations. These guides assume y | [[deploy-k8s-service]] | Deploy a new service to Kubernetes via ArgoCD | | [[add-ansible-role]] | Add a new Ansible role for indri services | | [[create-release-artifact-workflow]] | Build artifacts and publish to Forgejo packages | +| [[build-container-image]] | Build and release a custom container image via Dagger | ## Configuration