Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-architecture, runnable Docker image #19

Merged
merged 1 commit into from
Aug 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 59 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,65 @@
FROM golang:1.16
# Single source stage
FROM --platform=$BUILDPLATFORM golang:1.16 as fetcher

RUN apt-get update -yy && \
apt-get install -yy \
autoconf \
libtool \
portaudio19-dev
# Bring the source in
COPY . "$GOPATH"/src/github.com/albanseurat/goplay2
WORKDIR "$GOPATH"/src/github.com/albanseurat/goplay2

COPY . /go/src/github.com/albanseurat/goplay2/
WORKDIR /go/src/github.com/albanseurat/goplay2/
RUN GOOS=linux make
# Patch source to be able to link dynamically as debian packages do not provide static version of libfdk
RUN sed -Ei 's/-l:libfdk-aac.a/-lfdk-aac/' ./codec/aac.go

# Actual cross-compiling image, per target platform
FROM --platform=$BUILDPLATFORM fetcher as builder

ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT

ENV GOOS=$TARGETOS
ENV GOARCH=$TARGETARCH
ENV CGO_ENABLED=1

RUN sed -Ei 's/main$/main non-free/g' /etc/apt/sources.list; \
DEB_TARGET_ARCH="$(echo "$TARGETARCH$TARGETVARIANT" | sed -e "s/^armv6$/armel/" -e "s/^armv7$/armhf/" -e "s/^ppc64le$/ppc64el/" -e "s/^386$/i386/")"; \
dpkg --add-architecture "$DEB_TARGET_ARCH"; \
apt-get update; \
apt-get install -qq --no-install-recommends \
autoconf \
libtool \
crossbuild-essential-"$DEB_TARGET_ARCH" \
libfdk-aac1:"$DEB_TARGET_ARCH" \
libfdk-aac-dev:"$DEB_TARGET_ARCH" \
portaudio19-dev:"$DEB_TARGET_ARCH"

RUN eval "$(dpkg-architecture -A "$(echo "$TARGETARCH$TARGETVARIANT" | sed -e "s/^armv6$/armel/" -e "s/^armv7$/armhf/" -e "s/^ppc64le$/ppc64el/" -e "s/^386$/i386/")")"; \
export CC="${DEB_TARGET_GNU_TYPE}-gcc"; \
export CXX="${DEB_TARGET_GNU_TYPE}-g++"; \
export GOARM="$(printf "%s" "$TARGETVARIANT" | tr -d v)"; \
go build -trimpath -buildmode=pie -tags "netgo osusergo cgo" -ldflags "-s -w" -o /dist/goplay2 .

# Runtime image
FROM debian:buster

RUN sed -Ei 's/main$/main non-free/g' /etc/apt/sources.list; \
apt-get update; \
apt-get install -qq --no-install-recommends \
libportaudio2 \
pulseaudio-utils \
libfdk-aac1; \
apt-get -qq autoremove && \
apt-get -qq clean && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /tmp/* && \
rm -rf /var/tmp/*

FROM debian:jessie
RUN apt-get update -yy && \
apt-get install -yy libportaudio2
WORKDIR /opt
COPY --from=0 /go/src/github.com/albanseurat/goplay2/goplay2 .
CMD ["/opt/goplay2"]

RUN adduser --system --no-create-home --home /nonexistent --gecos "in dockerfile user" --uid 1000 goplay
RUN chown 1000 /opt

COPY --from=builder --chown=1000:root /dist/goplay2 .
RUN setcap 'cap_net_bind_service+ep' ./goplay2

USER goplay

CMD ["/opt/goplay2"]
41 changes: 35 additions & 6 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,53 @@ brew install portaudio fdk-aac go

### Docker image

You can build the image to test Linux build and that the service run properly
You can build and run the image to quickly test goplay, though this is experimental right now and comes with caveats.

* Build the image

The following platforms are supported: linux/amd64, linux/arm64, linux/arm/v7.
Other platforms should also build.

You can build with docker directly:
```shell
docker build -t albanseurat/goplay2:latest .
docker build --platform=linux/amd64 -t you/goplay2 .
```

Or with buildctl / buildkit if you want to assemble a multi-arch image.

* Run the container

This image currently does not provide a way to run pulseaudio inside the container itself, and pulseaudio is expected
to be available and running on the host for this to work.

On debian variants, this is typically as simple as:
```
sudo apt-get install pulseaudio
pulseaudio --start
```

To then run the container
```shell
docker run -p 7000:7000 -it albanseurat/goplay2:latest
export STATION_NAME="GoplaySpeaker"

mkdir -p "$(pwd)/$STATION_NAME"

docker run \
--rm \
--name goplay \
--volume "$(pwd)/$STATION_NAME":/opt/"$STATION_NAME" \
--volume /run/user/1000/pulse/native:/pulse \
--env PULSE_SERVER=/pulse \
--net host \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--read-only \
you/goplay2 ./goplay2 -n "$STATION_NAME"
```

#### Acknowledgments
Note that mDNS by design will only work with networking mode "host" (recommended for beginners) or (mac/ip)vlan.

* Docker build is intended to test building the program on Linux platform
* Bonjour/mDns implementation needs to be changed to allow exposing airplay service outside docker container
#### Acknowledgments

## Run

Expand Down