feat: migrate to LiteFS-supervised container architecture
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m2s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m2s
This commit is contained in:
60
.github/workflows/build-and-push.yml
vendored
Normal file
60
.github/workflows/build-and-push.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
name: Build and Push Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
outputs:
|
||||||
|
container_sha: ${{ github.sha }}
|
||||||
|
registry_url: ${{ steps.registry.outputs.url }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set registry URL
|
||||||
|
id: registry
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.server_url }}" = "https://github.com" ]; then
|
||||||
|
echo "url=ghcr.io" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
# Extract domain from server_url (e.g. gitea.service.dc1.fbleagh.duckdns.org)
|
||||||
|
echo "url=${{ github.server_url }}" | sed 's|https://||' >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Log in to Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ steps.registry.outputs.url }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.PACKAGE_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build and push multi-arch Docker image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: |
|
||||||
|
${{ steps.registry.outputs.url }}/${{ github.repository }}:latest
|
||||||
|
${{ steps.registry.outputs.url }}/${{ github.repository }}:${{ github.sha }}
|
||||||
|
build-args: |
|
||||||
|
COMMIT_SHA=${{ github.sha }}
|
||||||
|
cache-from: type=registry,ref=${{ steps.registry.outputs.url }}/${{ github.repository }}:buildcache
|
||||||
|
cache-to: type=registry,ref=${{ steps.registry.outputs.url }}/${{ github.repository }}:buildcache,mode=max
|
||||||
|
labels: org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||||
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Stage 1: Get LiteFS binary
|
||||||
|
FROM flyio/litefs:0.5 AS litefs
|
||||||
|
|
||||||
|
# Stage 2: Final image
|
||||||
|
FROM ghcr.io/navidrome/navidrome:latest
|
||||||
|
|
||||||
|
# Install FUSE and CA certificates (needed for LiteFS)
|
||||||
|
USER root
|
||||||
|
RUN apk add --no-cache fuse3 ca-certificates
|
||||||
|
|
||||||
|
# Copy LiteFS binary
|
||||||
|
COPY --from=litefs /usr/local/bin/litefs /usr/local/bin/litefs
|
||||||
|
|
||||||
|
# Copy LiteFS configuration
|
||||||
|
COPY litefs.yml /etc/litefs.yml
|
||||||
|
|
||||||
|
# We'll use environment variables for most LiteFS settings,
|
||||||
|
# but the baked-in config provides the structure.
|
||||||
|
# LiteFS will mount the FUSE fs and then execute Navidrome.
|
||||||
|
ENTRYPOINT ["litefs", "mount", "--", "/app/navidrome"]
|
||||||
27
litefs.yml
Normal file
27
litefs.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# LiteFS configuration for Navidrome
|
||||||
|
fuse:
|
||||||
|
dir: "/data"
|
||||||
|
|
||||||
|
data:
|
||||||
|
dir: "/var/lib/litefs"
|
||||||
|
|
||||||
|
# Use Consul for leader election
|
||||||
|
lease:
|
||||||
|
type: "consul"
|
||||||
|
consul:
|
||||||
|
url: "${CONSUL_URL}"
|
||||||
|
key: "litefs/navidrome"
|
||||||
|
|
||||||
|
# The HTTP Proxy routes traffic to handle write-forwarding
|
||||||
|
proxy:
|
||||||
|
addr: ":${PORT}"
|
||||||
|
target: "localhost:4533"
|
||||||
|
db: "navidrome.db"
|
||||||
|
passthrough:
|
||||||
|
- "*.js"
|
||||||
|
- "*.css"
|
||||||
|
- "*.png"
|
||||||
|
- "*.jpg"
|
||||||
|
- "*.jpeg"
|
||||||
|
- "*.gif"
|
||||||
|
- "*.svg"
|
||||||
89
navidrome-litefs-v2.nomad
Normal file
89
navidrome-litefs-v2.nomad
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
job "navidrome-litefs" {
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "service"
|
||||||
|
|
||||||
|
constraint {
|
||||||
|
attribute = "${attr.kernel.name}"
|
||||||
|
value = "linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
group "navidrome" {
|
||||||
|
count = 2
|
||||||
|
|
||||||
|
constraint {
|
||||||
|
distinct_hosts = true
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "host"
|
||||||
|
port "http" {}
|
||||||
|
}
|
||||||
|
|
||||||
|
task "navidrome" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
# Update this to match your actual registry and image name
|
||||||
|
image = "gitea.service.dc1.fbleagh.duckdns.org/sstent/navidrome-litefs:latest"
|
||||||
|
privileged = true # Needed for FUSE
|
||||||
|
network_mode = "host"
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/mnt/configs/navidrome_litefs:/var/lib/litefs",
|
||||||
|
"/mnt/Public/configs/navidrome:/shared_data",
|
||||||
|
"/mnt/Public/Downloads/Clean_Music:/music/CleanMusic:ro",
|
||||||
|
"/mnt/Public/Downloads/news/slskd/downloads:/music/slskd:ro",
|
||||||
|
"/mnt/Public/Downloads/incoming_music:/music/incomingmusic:ro"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
# LiteFS Config
|
||||||
|
CONSUL_URL = "http://${attr.unique.network.ip-address}:8500"
|
||||||
|
PORT = "${NOMAD_PORT_http}"
|
||||||
|
|
||||||
|
# Navidrome Config
|
||||||
|
ND_DATAFOLDER = "/local/data"
|
||||||
|
ND_CACHEFOLDER = "/shared_data/cache"
|
||||||
|
ND_CONFIGFILE = "/local/data/navidrome.toml"
|
||||||
|
|
||||||
|
# Database is on the LiteFS FUSE mount
|
||||||
|
ND_DBPATH = "/data/navidrome.db?_busy_timeout=30000&_journal_mode=WAL&_foreign_keys=on&synchronous=NORMAL"
|
||||||
|
|
||||||
|
ND_SCANSCHEDULE = "0"
|
||||||
|
ND_SCANNER_FSWATCHER_ENABLED = "false"
|
||||||
|
ND_LOGLEVEL = "info"
|
||||||
|
ND_REVERSEPROXYWHITELIST = "0.0.0.0/0"
|
||||||
|
ND_REVERSEPROXYUSERHEADER = "X-Forwarded-User"
|
||||||
|
}
|
||||||
|
|
||||||
|
service {
|
||||||
|
name = "navidrome"
|
||||||
|
tags = [
|
||||||
|
"navidrome",
|
||||||
|
"web",
|
||||||
|
"traefik.enable=true",
|
||||||
|
"urlprefix-/navidrome",
|
||||||
|
"tools",
|
||||||
|
"traefik.http.routers.navidromelan.rule=Host(`navidrome.service.dc1.consul`)",
|
||||||
|
"traefik.http.routers.navidromewan.rule=Host(`m.fbleagh.duckdns.org`)",
|
||||||
|
"traefik.http.routers.navidromewan.middlewares=dex@consulcatalog",
|
||||||
|
"traefik.http.routers.navidromewan.tls=true",
|
||||||
|
]
|
||||||
|
port = "http"
|
||||||
|
|
||||||
|
check {
|
||||||
|
type = "http"
|
||||||
|
path = "/app"
|
||||||
|
interval = "10s"
|
||||||
|
timeout = "2s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 500
|
||||||
|
memory = 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user