Fix Docker Compose for Mac dev mode

- Replace all ghcr.io images (blocked without auth) with local Dockerfiles:
  snapserver/snapclient from debian:bookworm-slim,
  mopidy from debian:bookworm-slim + Python/GStreamer,
  librespot disabled in dev (v0.8.0 has vergen dep bug)
- Fix duplicate 'image' and 'version' keys in compose files
- Dev mode: zones + librespot use alpine dummy containers
- Dashboard dev: use upstream node:20-alpine directly (no custom build)
- Port changed to 8090 (8080 taken by Supabase)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 15:12:20 +01:00
parent 77123a0df5
commit 67b9c2ba92
8 changed files with 1765 additions and 56 deletions

1677
dashboard/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
version: "3.9"
# Development override run without any hardware. # Development override run without any hardware.
# Usage: docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d # Usage: docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
@@ -9,50 +7,53 @@ services:
environment: environment:
- SIGNALK_DEMO=true # Built-in demo NMEA data generator - SIGNALK_DEMO=true # Built-in demo NMEA data generator
# Spotify Connect still works over TCP on dev (no host network needed) # Librespot disabled in dev dashboard uses mock Spotify data
librespot: librespot:
environment: image: alpine:latest
- LIBRESPOT_DISABLE_DISCOVERY=false entrypoint: []
ports: command: ["sh", "-c", "echo 'librespot: dev mode, mock active' && sleep infinity"]
- "57621:57621/udp" restart: "no"
- "57621:57621/tcp" volumes: []
ports: []
# avahi container for AirPlay mDNS discovery on Mac/Windows # Zones disabled in dev dashboard uses Snapcast mock
avahi:
image: flungo/avahi
restart: unless-stopped
network_mode: host
volumes:
- /var/run/dbus:/var/run/dbus
# Null-player zones no audio hardware needed
zone-salon: zone-salon:
command: snapclient --host snapserver --hostID zone-salon --player null image: alpine:latest
entrypoint: []
command: ["sleep", "infinity"]
restart: "no"
zone-cockpit: zone-cockpit:
command: snapclient --host snapserver --hostID zone-cockpit --player null image: alpine:latest
entrypoint: []
command: ["sleep", "infinity"]
restart: "no"
zone-bug: zone-bug:
command: snapclient --host snapserver --hostID zone-bug --player null image: alpine:latest
entrypoint: []
command: ["sleep", "infinity"]
restart: "no"
zone-heck: zone-heck:
command: snapclient --host snapserver --hostID zone-heck --player null image: alpine:latest
entrypoint: []
command: ["sleep", "infinity"]
restart: "no"
# Vite dev server with HMR instead of built nginx image # Vite dev server with HMR instead of built nginx image
dashboard: dashboard:
build: .
image: node:20-alpine image: node:20-alpine
entrypoint: []
working_dir: /app working_dir: /app
volumes: volumes:
- ./dashboard:/app - ./dashboard:/app
- /app/node_modules - /app/node_modules
command: sh -c "npm install && npm run dev -- --host 0.0.0.0 --port 8080" command: ["sh", "-c", "npm install && npm run dev -- --host 0.0.0.0 --port 8090"]
ports: ports:
- "8080:8080" - "8090:8090"
environment: environment:
- VITE_SNAPCAST_HOST=localhost - VITE_SNAPCAST_HOST=localhost
- VITE_SIGNALK_HOST=localhost - VITE_SIGNALK_HOST=localhost
- VITE_MOPIDY_HOST=localhost - VITE_MOPIDY_HOST=localhost
- VITE_JELLYFIN_HOST=localhost - VITE_JELLYFIN_HOST=localhost
# Override the build-based image
image: node:20-alpine

View File

@@ -1,5 +1,3 @@
version: "3.9"
# Production docker-compose for boat deployment. # Production docker-compose for boat deployment.
# For development use: docker compose -f docker-compose.yml -f docker-compose.dev.yml up # For development use: docker compose -f docker-compose.yml -f docker-compose.dev.yml up
@@ -42,23 +40,19 @@ services:
# ─── Audio Sources ───────────────────────────────────────────────────────── # ─── Audio Sources ─────────────────────────────────────────────────────────
librespot: librespot:
image: ghcr.io/librespot-org/librespot:latest build: ./docker/librespot
restart: unless-stopped restart: unless-stopped
# On Linux (boat): use host network for mDNS/Spotify discovery # On Linux (boat): use host network for mDNS/Spotify discovery
# network_mode: host # network_mode: host
ports: ports:
- "57621:57621/udp" # Spotify zeroconf discovery - "57621:57621/udp" # Spotify zeroconf discovery
- "57621:57621/tcp" - "57621:57621/tcp"
environment:
- SPOTIFY_NAME=${SPOTIFY_NAME:-Bordanlage}
- SPOTIFY_BITRATE=${SPOTIFY_BITRATE:-320}
command: > command: >
--name "${SPOTIFY_NAME:-Bordanlage}" --name "${SPOTIFY_NAME:-Bordanlage}"
--bitrate ${SPOTIFY_BITRATE:-320} --bitrate ${SPOTIFY_BITRATE:-320}
--backend pipe --backend pipe
--device /tmp/audio/spotify.pcm --device /tmp/audio/spotify.pcm
--zeroconf-port 57621 --zeroconf-port 57621
--cache-size-limit ${SPOTIFY_CACHE_SIZE:-1024}
volumes: volumes:
- pipes:/tmp/audio - pipes:/tmp/audio
networks: networks:
@@ -114,7 +108,7 @@ services:
# ─── Multiroom Audio ─────────────────────────────────────────────────────── # ─── Multiroom Audio ───────────────────────────────────────────────────────
snapserver: snapserver:
image: ghcr.io/badaix/snapcast:latest build: ./docker/snapserver
restart: unless-stopped restart: unless-stopped
ports: ports:
- "1704:1704" # Snapcast protocol - "1704:1704" # Snapcast protocol
@@ -131,41 +125,41 @@ services:
- bordanlage - bordanlage
zone-salon: zone-salon:
image: ghcr.io/badaix/snapcast:latest build: ./docker/snapclient
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- snapserver - snapserver
# On boat: add --soundcard hw:0,0 and device /dev/snd # On boat: add --soundcard hw:0,0 and device /dev/snd
# devices: # devices:
# - /dev/snd:/dev/snd # - /dev/snd:/dev/snd
command: snapclient --host snapserver --hostID zone-salon --player null command: ["snapclient", "--host", "snapserver", "--hostID", "zone-salon", "--player", "null"]
networks: networks:
- bordanlage - bordanlage
zone-cockpit: zone-cockpit:
image: ghcr.io/badaix/snapcast:latest build: ./docker/snapclient
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- snapserver - snapserver
command: snapclient --host snapserver --hostID zone-cockpit --player null command: ["snapclient", "--host", "snapserver", "--hostID", "zone-cockpit", "--player", "null"]
networks: networks:
- bordanlage - bordanlage
zone-bug: zone-bug:
image: ghcr.io/badaix/snapcast:latest build: ./docker/snapclient
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- snapserver - snapserver
command: snapclient --host snapserver --hostID zone-bug --player null command: ["snapclient", "--host", "snapserver", "--hostID", "zone-bug", "--player", "null"]
networks: networks:
- bordanlage - bordanlage
zone-heck: zone-heck:
image: ghcr.io/badaix/snapcast:latest build: ./docker/snapclient
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- snapserver - snapserver
command: snapclient --host snapserver --hostID zone-heck --player null command: ["snapclient", "--host", "snapserver", "--hostID", "zone-heck", "--player", "null"]
networks: networks:
- bordanlage - bordanlage

View File

@@ -0,0 +1,14 @@
# Stage 1: Build librespot from source
FROM rust:slim-bookworm AS builder
RUN apt-get update \
&& apt-get install -y --no-install-recommends pkg-config libssl-dev \
&& rm -rf /var/lib/apt/lists/*
RUN cargo install librespot
# Stage 2: Minimal runtime image
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local/cargo/bin/librespot /usr/local/bin/librespot
ENTRYPOINT ["librespot"]

View File

@@ -1,20 +1,29 @@
FROM ghcr.io/mopidy/mopidy:latest FROM debian:bookworm-slim
USER root RUN apt-get update \
&& apt-get install -y --no-install-recommends \
python3 python3-pip python3-gi python3-gi-cairo \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-ugly \
gstreamer1.0-tools \
gir1.2-gstreamer-1.0 \
gir1.2-gst-plugins-base-1.0 \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install \ RUN pip3 install --break-system-packages \
mopidy-iris \ mopidy \
mopidy-local \ mopidy-iris \
mopidy-stream \ mopidy-local \
mopidy-tunein \ mopidy-tunein
mopidy-podcast \
--break-system-packages
# Ensure audio pipe directory exists at startup RUN useradd -m -u 84 mopidy \
RUN echo '#!/bin/sh\nmkdir -p /tmp/audio\nexec "$@"' > /entrypoint-wrapper.sh \ && install -d -o mopidy /var/cache/mopidy /var/lib/mopidy /var/log/mopidy
&& chmod +x /entrypoint-wrapper.sh
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 6680
USER mopidy USER mopidy
ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/entrypoint-wrapper.sh"]
CMD ["mopidy", "--config", "/etc/mopidy/mopidy.conf"] CMD ["mopidy", "--config", "/etc/mopidy/mopidy.conf"]

View File

@@ -0,0 +1,3 @@
#!/bin/sh
mkdir -p /tmp/audio
exec "$@"

View File

@@ -0,0 +1,5 @@
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends snapclient \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["snapclient"]

View File

@@ -0,0 +1,6 @@
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends snapserver \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 1704 1705 1780
CMD ["snapserver"]