Skip to content

Commit 6f50af9

Browse files
authored
#104 Revamped (#105)
- build using cargo - compile with support for libmdns - support zeroconf backend with new variable ZERCONF_BACKEND
1 parent 79eec45 commit 6f50af9

File tree

6 files changed

+129
-53
lines changed

6 files changed

+129
-53
lines changed

.github/workflows/docker-multi-arch.yml

+19-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
fail-fast: false
1717
matrix:
18-
base: ["bookworm", "bullseye"]
18+
base: ["bookworm"]
1919

2020
steps:
2121
- name: Checkout
@@ -31,13 +31,24 @@ jobs:
3131
ref=${{ github.ref }}
3232
echo "REF: ["$ref"]"
3333
34-
declare -A base_image_from_matrix
35-
base_image_from_matrix[bullseye]=debian:bullseye-slim
36-
base_image_from_matrix[bookworm]=debian:bookworm-slim
34+
declare -A rust_image_from_matrix
35+
rust_image_from_matrix[bullseye]=library/rust:slim-bullseye
36+
rust_image_from_matrix[bookworm]=library/rust:slim-bookworm
37+
38+
declare -A base_images
39+
40+
base_images[bookworm]=library/debian:bookworm-slim
41+
base_images[bullseye]=library/debian:bullseye-slim
42+
43+
select_rust_image=${rust_image_from_matrix[${{ matrix.base }}]}
44+
if [ -z "${select_rust_image}" ]; then
45+
select_rust_image=library/rust:slim
46+
fi
47+
echo "Select Rust Image [" $select_rust_image "]"
3748
3849
select_base_image=${base_image_from_matrix[${{ matrix.base }}]}
3950
if [ -z "${select_base_image}" ]; then
40-
select_base_image=debian:buster-slim
51+
select_base_image=library/debian:stable-slim
4152
fi
4253
echo "Select Base Image [" $select_base_image "]"
4354
@@ -103,7 +114,7 @@ jobs:
103114
fi
104115
echo "Building tags: ["${tags}"]"
105116
echo "RELEASE_TAGS=${tags}" >> $GITHUB_ENV
106-
echo "BASE_IMAGE=${select_base_image}" >> $GITHUB_ENV
117+
echo "RUST_IMAGE=${select_rust_image}" >> $GITHUB_ENV
107118
- name: Set up QEMU
108119
uses: docker/setup-qemu-action@v3
109120
with:
@@ -121,7 +132,8 @@ jobs:
121132
with:
122133
context: .
123134
build-args: |
135+
RUST_IMAGE=${{ env.RUST_IMAGE }}
124136
BASE_IMAGE=${{ env.BASE_IMAGE }}
125-
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
137+
platforms: linux/amd64,linux/arm64/v8
126138
push: true
127139
tags: ${{ env.RELEASE_TAGS }}

Dockerfile

+45-22
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,53 @@
1-
ARG BASE_IMAGE
2-
FROM ${BASE_IMAGE} AS base
3-
ARG USE_APT_PROXY
1+
ARG RUST_IMAGE=""
2+
ARG BASE_IMAGE=""
3+
FROM ${RUST_IMAGE:-library/rust:slim} AS base
44

55
RUN mkdir -p /app/bin
66
RUN mkdir -p /app/conf
77
RUN mkdir -p /app/doc
88

9-
COPY app/conf/01-apt-proxy /app/conf/
9+
# Add build dependencies
10+
RUN apt-get update
11+
RUN apt-get install -y build-essential
12+
RUN apt-get install -y cmake
13+
RUN apt-get install -y libclang-dev
14+
RUN apt-get install -y libasound2-dev
15+
RUN apt-get install -y libpulse-dev
16+
RUN apt-get install -y libavahi-compat-libdnssd-dev
17+
RUN apt-get install -y pkg-config
1018

11-
RUN if [ "$USE_APT_PROXY" = "Y" ]; then \
12-
echo "Using apt proxy"; \
13-
cp /app/conf/01-apt-proxy /etc/apt/apt.conf.d/; \
14-
cat /etc/apt/apt.conf.d/01-apt-proxy; \
15-
else \
16-
echo "Building without proxy"; \
17-
fi
19+
# runtime
20+
RUN apt-get install -y libavahi-compat-libdnssd1
1821

19-
RUN apt-get update
20-
RUN apt-get install -y libasound2
21-
RUN apt-get install -y alsa-utils
22+
RUN apt-get install -y git
23+
24+
RUN mkdir /src
25+
WORKDIR /src
26+
RUN git clone --branch master https://github.com/librespot-org/librespot.git
27+
WORKDIR /src/librespot
28+
RUN CARGO_NET_GIT_FETCH_WITH_CLI=true cargo build --release --no-default-features --features "alsa-backend pulseaudio-backend with-avahi with-dns-sd with-libmdns"
29+
RUN cp /src/librespot/target/release/librespot /usr/bin/librespot
30+
WORKDIR /
31+
# RUN rm -Rf /src
32+
33+
RUN rm -rf /var/lib/apt/lists/*
2234

23-
RUN apt-get -y install curl
24-
RUN curl -sL https://dtcooper.github.io/raspotify/install.sh | sh
35+
FROM ${BASE_IMAGE:-library/debian:stable-slim} AS intermediate
2536

26-
RUN if [ "$USE_APT_PROXY" = "Y" ]; then \
27-
rm /etc/apt/apt.conf.d/01-apt-proxy; \
28-
fi
37+
COPY --from=base /usr/bin/librespot /usr/bin/librespot
2938

39+
# Add runtime dependencies only
40+
RUN apt-get update
41+
RUN apt-get install -y libasound2
42+
RUN apt-get install -y alsa-utils
43+
RUN apt-get install -y --no-install-recommends pulseaudio-utils
44+
RUN apt-get install -y ca-certificates
45+
RUN apt-get install -y libavahi-compat-libdnssd1
46+
3047
RUN rm -rf /var/lib/apt/lists/*
3148

3249
FROM scratch
33-
COPY --from=base / /
50+
COPY --from=intermediate / /
3451

3552
LABEL maintainer="GioF71"
3653
LABEL source="https://github.com/GioF71/librespot-docker"
@@ -73,6 +90,7 @@ ENV DISABLE_DISCOVERY=""
7390
ENV DITHER=""
7491

7592
ENV ZEROCONF_PORT=""
93+
ENV ZEROCONF_BACKEND=""
7694

7795
ENV ENABLE_VOLUME_NORMALISATION=""
7896
ENV NORMALISATION_METHOD=""
@@ -102,17 +120,22 @@ ENV ONEVENT_POST_ENDPOINT=""
102120

103121
ENV ENABLE_OAUTH=""
104122

123+
ENV CARGO_HOME "/cargo-home"
124+
ENV ADDITIONAL_ARGUMENTS=""
125+
105126
VOLUME /data/cache
106127
VOLUME /data/system-cache
107128
VOLUME /user/config
108129

130+
VOLUME /cargo-home
131+
109132
COPY README.md /app/doc/
110133

111134
RUN mkdir -p /app/assets
112135

113136
COPY app/assets/pulse-client-template.conf /app/assets/
114137

115-
RUN which librespot
138+
#RUN which librespot
116139

117140
COPY app/bin/run-librespot.sh /app/bin/
118141
COPY app/bin/read-file.sh /app/bin/
@@ -122,4 +145,4 @@ COPY app/bin/post-event-data.sh /app/bin/
122145
RUN chmod u+x /app/bin/*.sh
123146

124147
WORKDIR /app/bin
125-
ENTRYPOINT ["/app/bin/run-librespot.sh"]
148+
ENTRYPOINT ["/app/bin/run-librespot.sh"]

README.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ First and foremost, the reference to the awesome project:
88

99
[Librespot](https://github.com/librespot-org/librespot)
1010

11-
I am also currently relying on Raspotify because building images from crates.io fails for armhf platfrom. So here is the reference to this other excellent project:
11+
For a long time, I have also been relying on Raspotify because building images from crates.io fails for armhf platfrom. So here is the reference to this other excellent project:
1212

1313
[Raspotify](https://github.com/dtcooper/raspotify)
1414

15+
Since the first days of 2025, we are building the images directly from source code.
16+
1517
## Links
1618

1719
REPOSITORY TYPE|LINK
1820
:---|:---
1921
Git Repository|[GitHub](https://github.com/giof71/librespot-docker)
2022
Docker Images|[DockerHub](https://hub.docker.com/r/giof71/librespot)
2123

22-
The `latest` image is published daily, so it will include the same version of [Librespot](https://github.com/librespot-org/librespot) included in the current release of [Raspotify](https://github.com/dtcooper/raspotify).
23-
2424
## Why
2525

2626
I prepared this Dockerfile Because I wanted to be able to install librespot easily on any machine (provided the architecture is amd64, armhf or arm64). Also I wanted to be able to configure and govern the parameter easily, maybe through a webapp like Portainer.
@@ -38,10 +38,11 @@ This command will output one line if the current user does belong to the "docker
3838

3939
The Dockerfile and the included scripts have been tested on the following distros:
4040

41-
- Manjaro Linux with Gnome (amd64)
41+
- Manjaro Linux with Gnome/KDE (amd64)
4242
- Raspberry Pi 3/4 (32 and 64 bit)
4343
- Asus Tinkerboard with DietPi ([don't let that board run at a very low minimum frequency](https://github.com/GioF71/squeezelite-docker/blob/main/doc/asus-tinkerboard.md))
4444
- OSMC on Raspberry Pi 4
45+
- Moode Audio on Raspberry Pi 3/4
4546

4647
As I test the Dockerfile on more platforms, I will update this list.
4748

@@ -90,6 +91,7 @@ AP_PORT||Connect to an AP with a specified port. If no AP with that port is pres
9091
DISABLE_DISCOVERY||Disable zeroconf discovery mode. `Y` or `y` to disable discovery.
9192
DITHER||Dither algorithm: none, gpdf, tpdf, tpdf_hp. Defaults to tpdf for formats S16, S24, S24_3 and none for other formats.
9293
ZEROCONF_PORT||The port the internal server advertises over zeroconf: `1` - `65535`. Ports <= `1024` may require root privileges.
94+
ZEROCONF_BACKEND||Select the desidered backend, valid values are `avahi`, `libmdns`, `dns-sd`. With the latest builds, I am getting good results with `libmdns`, so it will be the default if discovery is not disabled
9395
ENABLE_VOLUME_NORMALISATION||Enables volume normalisation for librespot. `Y` or `y` to enable.
9496
NORMALISATION_METHOD||Specify the normalisation method to use: `basic`, `dynamic`. Defaults to `dynamic`.
9597
NORMALISATION_GAIN_TYPE||Specify the normalisation gain type to use: `track`, `album`, `auto`. Defaults to `auto`.
@@ -111,6 +113,7 @@ ONEVENT_COMMAND||Specifies the name of a user defined script/executable that wil
111113
ONEVENT_POST_ENDPOINT||Send a `POST` request with event data to the specified endpoint URL whenever a player event occurs. Request body is `json` encoded and contains all available fields specified by the [librespot's player event handler](https://github.com/librespot-org/librespot/blob/dev/src/player_event_handler.rs). Will be ignored if `ONEVENT_COMMAND` is set.
112114
ENABLE_OAUTH||Set to `headless` to enable OAUTH authentication. You will need to run the container interactively the first time. Recommended to enable when caching is also enabled.
113115
LOG_COMMAND_LINE||Set to `Y` or `y` to enable, `N` or `n` to disable. Defaults to `Y`.
116+
ADDITIONAL_ARGUMENTS||Use this to add additional arguments to be appended to the command line
114117

115118
### Volumes
116119

app/bin/run-librespot.sh

+29-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ current_user_id=$(id -u)
77
echo "Current user id is [$current_user_id]"
88

99
DEFAULT_STARTUP_DELAY_SEC=0
10+
DEFAULT_ZEROCONF_BACKEND=libmdns
11+
12+
# enabled unless explicitly disabled
13+
discovery_enabled=1
1014

1115
declare -A file_dict
1216

@@ -20,6 +24,7 @@ if [ -f "$CREDENTIALS_FILE" ]; then
2024
SPOTIFY_PASSWORD=$(get_value "SPOTIFY_PASSWORD" $PARAMETER_PRIORITY)
2125
fi
2226

27+
# CMD_LINE="/usr/bin/librespot"
2328
CMD_LINE="/usr/bin/librespot"
2429

2530
DEFAULT_UID=1000
@@ -128,7 +133,7 @@ if [ -n "$SPOTIFY_PASSWORD" ]; then
128133
CMD_LINE="$CMD_LINE --password '$SPOTIFY_PASSWORD'"
129134
fi
130135

131-
if [ -n "$BACKEND" ]; then
136+
if [ -n "${BACKEND}" ]; then
132137
CMD_LINE="$CMD_LINE --backend $BACKEND"
133138
fi
134139

@@ -224,14 +229,28 @@ fi
224229

225230
if [ "${DISABLE_DISCOVERY^^}" = "Y" ]; then
226231
CMD_LINE="$CMD_LINE --disable-discovery"
232+
discovery_enabled=0
227233
fi
228234

229235
if [ -n "$DITHER" ]; then
230236
CMD_LINE="$CMD_LINE --dither $DITHER"
231237
fi
232238

233-
if [ -n "$ZEROCONF_PORT" ]; then
234-
CMD_LINE="$CMD_LINE --zeroconf-port $ZEROCONF_PORT"
239+
# zeroconf
240+
if [ $discovery_enabled -eq 1 ]; then
241+
echo "Discovery is enabled."
242+
if [ -n "$ZEROCONF_PORT" ]; then
243+
echo "Using zeroconf port [$ZEROCONF_PORT}]"
244+
CMD_LINE="$CMD_LINE --zeroconf-port $ZEROCONF_PORT"
245+
fi
246+
zeroconf_backend=$DEFAULT_ZEROCONF_BACKEND
247+
if [[ -n "${ZEROCONF_BACKEND}" ]]; then
248+
zeroconf_backend=$ZEROCONF_BACKEND
249+
fi
250+
echo "Using zeroconf backend [${zeroconf_backend}]"
251+
CMD_LINE="$CMD_LINE --zeroconf-backend $zeroconf_backend"
252+
else
253+
echo "Discovery is not enabled."
235254
fi
236255

237256
if [ "${ENABLE_VOLUME_NORMALISATION^^}" = "Y" ]; then
@@ -301,11 +320,17 @@ if [[ -n "${ENABLE_OAUTH}" ]]; then
301320
fi
302321
fi
303322

323+
if [[ -n "${ADDITIONAL_ARGUMENTS}" ]]; then
324+
echo "ADDITIONAL_ARGUMENTS=[${ADDITIONAL_ARGUMENTS}]"
325+
CMD_LINE="$CMD_LINE ${ADDITIONAL_ARGUMENTS}"
326+
else
327+
echo "Additional arguments have not been specified."
328+
fi
329+
304330
if [[ -z "${LOG_COMMAND_LINE}" || "${LOG_COMMAND_LINE^^}" = "Y" ]]; then
305331
ur=$(printf '*%.0s' $(seq 1 ${#SPOTIFY_USERNAME}))
306332
pr=$(printf '*%.0s' $(seq 1 ${#SPOTIFY_PASSWORD}))
307333
some_asterisks=$(printf '*%.0s' $(seq 1 16))
308-
309334
safe=$CMD_LINE
310335
safe=$(echo "${safe/"$SPOTIFY_USERNAME"/"$some_asterisks"}")
311336
safe=$(echo "${safe/"$SPOTIFY_PASSWORD"/"$some_asterisks"}")

app/conf/01-apt-proxy

-2
This file was deleted.

build.sh

+29-14
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,50 @@
11
#!/bin/bash
22

3+
declare -A rust_images
4+
5+
rust_images[stable]=library/rust:slim
6+
rust_images[bookworm]=library/rust:slim-bookworm
7+
rust_images[bullseye]=library/rust:slim-bullseye
8+
39
declare -A base_images
410

5-
base_images[bullseye]=debian:bullseye-slim
6-
base_images[buster]=debian:buster-slim
7-
base_images[bookworm]=debian:bookworm-slim
8-
base_images[kinetic]=ubuntu:kinetic
9-
base_images[focal]=ubuntu:focal
10-
base_images[jammy]=ubuntu:jammy
11+
base_images[stable]=library/debian:stable-slim
12+
base_images[bookworm]=library/debian:bookworm-slim
13+
base_images[bullseye]=library/debian:bullseye-slim
14+
15+
# DEFAULT_RUST_IMAGE=bookworm
16+
# DEFAULT_TAG=latest
17+
DEFAULT_RUST_IMAGE=library/rust:slim
18+
DEFAULT_BASE_IMAGE=library/debian:stable-slim
1119

12-
DEFAULT_BASE_IMAGE=bookworm
1320
DEFAULT_TAG=latest
1421
DEFAULT_USE_PROXY=N
1522
DEFAULT_BRANCH=master
1623

1724
tag=$DEFAULT_TAG
1825
use_proxy=$DEFAULT_USE_PROXY
19-
use_branch=$DEFAULT_BRANCH
2026

21-
while getopts b:t:p:v: flag
27+
while getopts r:b:t:p:v: flag
2228
do
2329
case "${flag}" in
30+
r) rust_image=${OPTARG};;
2431
b) base_image=${OPTARG};;
2532
t) tag=${OPTARG};;
2633
p) proxy=${OPTARG};;
2734
v) select_branch=${OPTARG};;
2835
esac
2936
done
3037

38+
echo "rust_image: $rust_image";
3139
echo "base_image: $base_image";
3240
echo "tag: $tag";
3341
echo "proxy: $proxy";
3442
echo "branch: $select_branch"
3543

44+
if [ -z "${rust_image}" ]; then
45+
rust_image=$DEFAULT_RUST_IMAGE
46+
fi
47+
3648
if [ -z "${base_image}" ]; then
3749
base_image=$DEFAULT_BASE_IMAGE
3850
fi
@@ -47,8 +59,11 @@ if [ -z "${tag}" ]; then
4759
tag="latest"
4860
fi
4961

50-
if [ -n "${select_branch}" ]; then
51-
use_branch=${select_branch}
62+
if [[ -z ${rust_images[$rust_image]} ]]; then
63+
echo "Image for ["$rust_image"] not found"
64+
select_rust_image=${rust_images[$DEFAULT_RUST_IMAGE]}
65+
else
66+
select_rust_image=${rust_images[$rust_image]}
5267
fi
5368

5469
if [[ -z ${base_images[$base_image]} ]]; then
@@ -58,14 +73,14 @@ else
5873
select_base_image=${base_images[$base_image]}
5974
fi
6075

76+
echo "Rust Image: ["$select_rust_image"]"
6177
echo "Base Image: ["$select_base_image"]"
6278
echo "Tag: ["$tag"]"
6379
echo "Proxy: ["$use_proxy"]"
64-
echo "Branch: ["$use_branch"]"
6580

66-
docker build . \
81+
docker buildx build . \
82+
--build-arg RUST_IMAGE=${select_rust_image} \
6783
--build-arg BASE_IMAGE=${select_base_image} \
68-
--build-arg USE_BRANCH=${use_branch} \
6984
--build-arg USE_APT_PROXY=${use_proxy} \
7085
-t giof71/librespot:$tag
7186

0 commit comments

Comments
 (0)