navidrome / navidrome

🎧☁️ Modern Music Server and Streamer compatible with Subsonic/Airsonic
https://www.navidrome.org
GNU General Public License v3.0
10.36k stars 797 forks source link

Prebuilt Raspberry Pi Docker images #92

Closed brandonaut closed 4 years ago

brandonaut commented 4 years ago

I know this is already on the roadmap, but I wanted a way to vote for it, so I created this issue :)

As far as I'm concerned, either a binary or a Docker image that works on Raspberry Pi (Raspbian Buster) would be great!

deluan commented 4 years ago

I did some research a while ago on how to build it for the Pi, I was planning to buy one to test it out, but if you can help testing it, I can try to work on this this week. Can you help with that?

brandonaut commented 4 years ago

Sure! I just got a PI 4, so I can test with that.

brandonaut commented 4 years ago

I tried to build it from source on the PI, but ran into what looked like a missing dependency on go-bindata:

go-bindata -fs -prefix "ui/build" -tags embed -nocompress -pkg assets -o assets/embedded_gen.go ui/build/...
/bin/sh: 1: go-bindata: not found

I haven't built anything with Go before, so I'm not familiar with the ecosystem. Is this a dependency that needs to be specified in the project somewhere?

deluan commented 4 years ago

You need to install go-bindata on your Pi system: go get -u github.com/go-bindata/go-bindata/...

Did you run the steps described in the "Build from source" section of the README? This is one of the tools installed my make setup

deluan commented 4 years ago

I was able to cross-compile Navidrome to ARM. I generated ARMv6, ARMv7 and ARM64 binaries, all should work on the Pi 4. Can you try on your system?

navidrome_v0.9.2-next_Linux_armv6.tar.gz navidrome_v0.9.2-next_Linux_armv7.tar.gz navidrome_v0.9.2-next_Linux_arm64.tar.gz

Let me know if they work

PS: Don't forget you still need ffmpeg on your Pi. If Raspbian does not include it, you can download from: https://johnvansickle.com/ffmpeg/

0xERR0R commented 4 years ago

I would recommend to use docker buildx to build cross-platform images. I tried this out with github actions, works nice. I used it in my project (Golang), see this workflow as reference, may be you can go the same way

deluan commented 4 years ago

Thanks @0xERR0R , I'll surely take a look. Right now I'm using bepsays/ci-goreleaser, it has the cross-compile toolset for various platforms, but misses Arm and Linux 32bits. I was able to add the dependencies for Arm, but having a hard time with Linux 32-bits.

0xERR0R commented 4 years ago

I think goreleaser can only build binaries, not docker images? But maybe I'm wrong.

deluan commented 4 years ago

It can, but I'm only using it to build the binaries. I use Docker Hub's automated builds to build the docker image, but I'll take a look at your solution, never used buildx before

brandonaut commented 4 years ago

@deluan The armv7 binary works great! Thanks for working on it.

deluan commented 4 years ago

Thanks for testing this out. I'll add the ARM binaries as part of the automated release. I'll keep this issue open to track the work on the cross-platform docker images

jvoisin commented 4 years ago

I can also confirm that the armv7 image is working flawlessly ♥

SenorSmartyPants commented 4 years ago

Please include armv8 64 bit images as well. Thanks.

0xERR0R commented 4 years ago

I tried to build the docker image for raspberry pi3 (arm7) and had following problems:

deluan commented 4 years ago

Hey @0xERR0R , thanks for taking a look at this. Here's the answers:

Let me know if you encounter any more issues

0xERR0R commented 4 years ago

I could successfully build multi-arch docker image for

with this GitHub Workflow. I tested the arm/v7 image on my pi3 and it works fine. The corresponding docker image is here.

I changed the Dockerfile as described (replaced ffmpeg with apk version, removed tini and changed the image).

deluan commented 4 years ago

Awesome! I'll take a look tonight. Wanna prepare a PR?

0xERR0R commented 4 years ago

PR is not a problem, but 2 points are still open: node version in image and ffmpeg. I saw that apk version installs a bunch of dependencies (libs) like lame etc. I don't know if all of them are necessary. I understand your point of view with "not polluting the image". But otherwise the apk version is optimized for alpine...

Same for node: Always using the same version is fine, but sometimes the fixed version will be removed from docker hub. Maybe it would be better to use always the last npm version?

Another point is the integration in your release job (setting of properly version tag in docker, ...)

I would like to help, but I do not have the big picture of your release in my head.

deluan commented 4 years ago

For Node, if you use 13-alpine3.10 as above, it will always use the latest Node 13 (right now it is 13.13-alpine3.10), so it is fine.

For the other points, I'll check later. Thanks!

deluan commented 4 years ago

Hey @0xERR0R I'm working on some pipeline improvements, and also playing with your modifications: https://github.com/deluan/navidrome-test/pull/1

I got the multiplatform docker image building working with builderx, but it is too slow and it is flaky, failing sometimes. Seems that the node build is super slow on ARM platforms.

Any ideas on how to optimize it? Maybe build the JS bundles before the docker build, as the bundles should be the same for all platforms? Thoughts?

0xERR0R commented 4 years ago

Yes, the build takes > 1h. The docker image will be built several times (one per architecture) and node build is really heavy. Since the web client artifact is not platform dependent, it could be possible to build it once and include into target docker image, which build platform dependent go binary. But this would introduce new step into the build pipeline for docker image. The current implementation is really simple: git checkout and docker build. No need to install any build tools, docker image does install everything and builds everything from scratch. Maybe you should create a docker image only for web client (will be build once for amd64) and use it as build image for go (per architecture)? I will try it today evening

0xERR0R commented 4 years ago

I tried to analyze the build log, you're right:

#28 [linux/arm64 jsbuilder 6/6] RUN npm run build
...
#28 1912. Compiled successfully.
...
#28 DONE 1912.4s

#53 [linux/amd64 jsbuilder 6/6] RUN npm run build
...
#53 253.6 Compiled successfully.
...
#53 DONE 256.1s

npm build ist very slow on arm. You are already building node stuff in "binaries", step "Build UI". Would it be possible to reuse this in later docker image buld step?

deluan commented 4 years ago

That was my idea. The only downside of this is that we would use a specific Dockerfile for this, that would be used only for the pipeline. But maybe it is not a big deal, considering the optimization it will bring. I'll try this later

0xERR0R commented 4 years ago

I tried following:

Build runs now in 19 min (instead of 1h 5m)

deluan commented 4 years ago

That's great! Thanks for this. A couple considerations:

  1. I think we should use a pair of separated Dockerfiles for the pipeline, and not change the current one. I'd like to allow devs to build their own image locally, which would be the purpose of the main Dockerfile.
  2. I think we should only remove the go test if we combine the build pipeline with the `release, to be sure the change that triggered the release is always tested.
  3. I don't think we need a webui image. We can just pass it from the binaries job to the docker job using "artifacts", like I do in my test build pipeline
0xERR0R commented 4 years ago
  1. agreed, it would be better to have a single docker file, which build everything, even if the build time is about 45 min.
  2. This with an extra image is a quick and dirty hack, if you have a better solution, this is great!
deluan commented 4 years ago

Hey @0xERR0R, using the binaries generated by goreleaser, I was able to bring down the total time to 13 mins. I need to test the Docker images on a Raspberry Pi, would you be able to test it? The image tag is deluan/deluan:0.0.11

I also reworked the workflows, combined them into one. Let me know what you think. The commit in question is this: https://github.com/deluan/navidrome-test/commit/ebae298d1e19ce8d0ee790ddcc3e9c15e65c303d

0xERR0R commented 4 years ago

A you sure, that the image name is deluan/deluan:0.0.11? I can't find it on docker hub...

deluan commented 4 years ago

Ops... the Docker repository was private. You can try again now :)

0xERR0R commented 4 years ago

Works like a charm!

deluan commented 4 years ago

Nice! Will merge the changes tonight! Thanks for all the help on this issue!

0xERR0R commented 4 years ago

@GitSchorsch Could you test it too please? ;)

GitSchorsch commented 4 years ago

@0xERR0R of course :-) Same result here (Raspbian on Raspberry Pi 4)! No problems. Fast and responsive all the time.

deluan commented 4 years ago

Fixed in #204 , thank you all for the help

github-actions[bot] commented 10 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.