diff --git a/docker/Dockerfile.musician b/docker/Dockerfile.musician index c145cfc..f743d27 100644 --- a/docker/Dockerfile.musician +++ b/docker/Dockerfile.musician @@ -17,14 +17,19 @@ RUN pip install --no-cache-dir --upgrade pip \ && pip install --no-cache-dir -r requirements_musician.txt COPY conjurer_musician/ ./ +COPY docker/entrypoint.musician.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh ENV PYTHONUNBUFFERED=1 \ CONJURER_MUSICIAN_HOST=0.0.0.0 \ CONJURER_MUSICIAN_PORT=5000 \ - CONJURER_MUSIC_FOLDER=/music + CONJURER_MUSIC_FOLDER=/music \ + CONJURER_MUSICIAN_BASE=/data \ + CONJURER_STREAM_TEMPLATE=/app/stream.html -# The mp3 library is mounted here (read-only is fine for serving). -VOLUME ["/music"] +# /music = the mp3 library (read-only ok); /data = writable playlists + logs. +VOLUME ["/music", "/data"] EXPOSE 5000 +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] CMD ["python", "conjurer_musician.py"] diff --git a/docker/entrypoint.musician.sh b/docker/entrypoint.musician.sh new file mode 100755 index 0000000..90cc1af --- /dev/null +++ b/docker/entrypoint.musician.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# Prepare the musician's writable volume so the web service starts cleanly on a +# fresh container. Existing files are never overwritten (preserves your data). +set -e + +DATA="${CONJURER_MUSICIAN_BASE:-/data}" +MUSIC="${CONJURER_MUSIC_FOLDER:-/music}" +mkdir -p "$DATA" "$DATA/logs" "$MUSIC" + +# The track-forwarding thread tails the Liquidsoap radio logs. When the radio +# runs separately (or hasn't started yet) these files may not exist; create +# them empty so the tailer waits instead of crashing. +for f in radio_log.log persistence.log; do + [ -e "$DATA/$f" ] || : > "$DATA/$f" +done + +# Ensure the managed playlists exist (routes/rescan also create them; this just +# avoids a first-tick race before the initial scan). +for f in all_playlist.playlist hit.playlist request.playlist priority_queue.playlist; do + [ -e "$DATA/$f" ] || : > "$DATA/$f" +done + +exec "$@" diff --git a/docs/deployment/DOCKER_PROXMOX.md b/docs/deployment/DOCKER_PROXMOX.md index 2f240a9..7f64a20 100644 --- a/docs/deployment/DOCKER_PROXMOX.md +++ b/docs/deployment/DOCKER_PROXMOX.md @@ -130,22 +130,60 @@ docker logs -f conjurer-librarian --- -## 3. Musician (VM-musician) — you will adapt this +## 3. Musician (VM-musician) The web service is container-ready (`docker/Dockerfile.musician` + -`compose.musician.yaml`). Note it containerises the **Flask file/playlist -service only**; the Liquidsoap radio (`radio_conjurer.liq`) and any +`compose.musician.yaml`). It containerises the **Flask file/playlist service +only** — the Liquidsoap radio (`radio_conjurer.liq`), `script.params` and any Samba/NFS share tooling are separate and typically stay on the host or a -dedicated setup. +dedicated setup (you'll adapt those yourself). + +### 3a. Two volumes: the library and the writable state + +| Mount | Container path | Holds | +|-------|---------------|-------| +| `/srv/musician/music` | `/music` (`CONJURER_MUSIC_FOLDER`) | your mp3 library (indexed/served) | +| `/srv/musician/data` | `/data` (`CONJURER_MUSICIAN_BASE`) | playlists, logs, `radio_log.log`/`persistence.log` | ```bash sudo mkdir -p /srv/musician/music /srv/musician/data +# point /srv/musician/music at (or copy in) your mp3s +``` + +### 3b. Preserve existing playlists/state (optional) + +If you already run the musician, copy its working playlists into the data +volume so nothing is regenerated from scratch: + +```bash +sudo cp all_playlist.playlist hit.playlist request.playlist \ + priority_queue.playlist playlist.json /srv/musician/data/ 2>/dev/null || true +``` + +The container's entrypoint (`docker/entrypoint.musician.sh`) creates any +missing playlists and touches `radio_log.log` / `persistence.log` empty so the +track-forwarding thread waits instead of crashing when the radio runs +elsewhere. It never overwrites files you copied in. + +### 3c. Configure and launch + +```bash cp docker/env/musician.env.example docker/env/musician.env -# edit: CONJURER_MAIN_BOT=http://BOT_VM_IP:5000, CONJURER_API_KEY, mount your mp3s at /music +# edit: CONJURER_MAIN_BOT=http://BOT_VM_IP:5000 and CONJURER_API_KEY (match the bot) docker compose -f docker/compose.musician.yaml up -d --build +docker logs -f conjurer-musician ``` +### 3d. Radio coupling (if you keep Liquidsoap separate) + +The musician only forwards "now playing" to the bot by tailing the radio's +`radio_log.log` / `persistence.log`. To wire them up, have Liquidsoap write +those two files into the same `/srv/musician/data` directory (or set +`CONJURER_RADIO_LOG` / `CONJURER_PERSISTENCE_LOG` to wherever it writes). The +`/stream` page template is served from the baked-in `/app/stream.html` +(override with `CONJURER_STREAM_TEMPLATE` if you customise it). + --- ## 4. Networking & auth