diff --git a/.github/workflows/publishImage.yml b/.github/workflows/publishImage.yml new file mode 100644 index 0000000..8aa3b28 --- /dev/null +++ b/.github/workflows/publishImage.yml @@ -0,0 +1,81 @@ +name: Publish Docker image to Dockerhub + +on: + workflow_dispatch: + push: +# uncomment to auto build when commits are pushed to listed branches +# branches: +# - 'master' + tags: + - '*.*.*' + # don't trigger if just updating docs + paths-ignore: + - 'README.md' + - '.github/**' + +jobs: + push_to_registry: + name: Build and push container images + if: ${{ github.event_name != 'pull_request' && (vars.GHCR_IMAGE_NAME != '' || vars.DOCKERHUB_IMAGE_NAME != '' ) }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - dockerfile: ./Dockerfile + suffix: '' + platforms: 'linux/amd64,linux/arm64' + # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token + permissions: + packages: write + contents: read + steps: + - name: Check out the repo + uses: actions/checkout@v4 + +# uncomment to enable dockerhub + +# - name: Log in to Docker Hub +# uses: docker/login-action@v3 +# with: +# username: ${{ secrets.DOCKER_USERNAME }} +# password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + # add to images list to enable dockerhub ${{ vars.DOCKERHUB_IMAGE_NAME }} + images: | + ${{ vars.GHCR_IMAGE_NAME }} + # generate Docker tags based on the following events/attributes + # https://github.com/docker/metadata-action/issues/247#issuecomment-1511259674 for NOT is default branch, eventually + tags: | + type=raw,value=latest,enable={{is_default_branch}},suffix=${{ matrix.suffix }} + type=ref,event=branch,enable=${{ !endsWith(github.ref, 'master') }},suffix=${{ matrix.suffix }} + type=semver,pattern={{version}},suffix=${{ matrix.suffix }} + flavor: | + latest=false + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ matrix.dockerfile }} + push: ${{ !env.ACT}} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: ${{ matrix.platforms }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5709cd6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +FROM ghcr.io/linuxserver/baseimage-alpine:3.20 as base + +FROM base as build + +ARG TARGETPLATFORM +ARG DOCKER_ARCH + +RUN \ + echo "**** install build packages ****" && \ + apk --no-cache add \ + binutils-gold \ + openssl \ + zlib \ + libstdc++ \ + dotnet6-sdk + +WORKDIR /app + +COPY --chown=root:root . /app + +RUN if [ "$DOCKER_ARCH" = "amd64" ] || [ "$TARGETPLATFORM" = "linux/amd64" ]; then export DN_RUNTIME=linux-musl-x64; echo 'Building x64'; fi \ + && if [ "$DOCKER_ARCH" = "arm64" ] || [ "$TARGETPLATFORM" = "linux/arm64" ]; then export DN_RUNTIME=linux-musl-arm64; echo 'Build ARM'; fi \ + && dotnet publish -c Release -r "$DN_RUNTIME" -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true -o build \ + && rm -f build/*.pdb + +FROM base as app + +ENV TZ=Etc/GMT + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN \ + echo "**** install runtime packages ****" && \ + apk --no-cache add \ + dotnet6-runtime && \ + echo "**** cleanup ****" && \ + rm -rf \ + /root/.cache \ + /tmp/* + +ENV DOCKER_MODS=linuxserver/mods:universal-cron + +COPY docker/root/ / + +COPY --from=build /app/build/* /usr/bin/ \ No newline at end of file diff --git a/README.md b/README.md index f7165b7..12e2ba7 100644 --- a/README.md +++ b/README.md @@ -574,3 +574,56 @@ sldl "artist=MC MENTAL" --aggregate --album ## Notes - For macOS builds you can use publish.sh to build the app. Download dotnet from https://dotnet.microsoft.com/en-us/download/dotnet/6.0, then run `chmod +x publish.sh && sh publish.sh`. For intel macs, uncomment the x64 and comment the arm64 section in publish.sh. - `--display single` and especially `double` can cause the printed lines to be duplicated or overwritten on some configurations. Use `simple` if that's an issue. + +## Docker + +A docker container for running `sldl` can be built from this repository. The image supports linux x86/ARM. + +To build and start container: + +```shell +clone https://github.com/fiso64/slsk-batchdl +cd slsk-batchdl +docker compose up -d +``` + +`exec` into the container to start using `sldl`: + +```shell +docker compose exec sldl sh +sldl --help +``` + +The compose stack mounts two directories relative to where `docker-compose.yml` is located which can be used for file management: + +* `/config` (at `./config` on host) - put your `sldl.conf` [configuration](#configuration-) in this directory and then use `sldl -c /config ...` to use your configuration in the container +* `/data` (at `./data` on host) - use as the download directory IE `sldl -p /data ...` + +### File Permissions + +If you are running Docker on a **Linux Host** you should specify `user:group` permissions of the user who owns the **configuration and data directory** on the host to avoid [docker file permission problems.](https://ikriv.com/blog/?p=4698) These can be specified using the [environmental variables **PUID** and **PGID**.](https://docs.linuxserver.io/general/understanding-puid-and-pgid) + +To get the UID and GID for the current user run these commands from a terminal: + +* `id -u` -- prints UID +* `id -g` -- prints GID + +Replace these with the corresponding variable (`PUID` `PGID`) in `docker-compose.yml`. + + +### Cron + +One or more `sldl` commands can be run on a schedule using [cron](https://en.wikipedia.org/wiki/Cron) built into the container. + +To create a schedule make a new file on the host `./config/crontabs/abc` and use it with the standard [crontab](https://en.wikipedia.org/wiki/Cron#Overview) syntax. + +Make sure to restart the container after any changes to the cron file are made. + +Example => Run `sldl` every Sunday at 1am, search for missing tracks from the specified Spotify playlist + +``` +# min hour day month weekday command +0 1 * * 0 sldl https://open.spotify.com/playlist/6sf1WR5grXGJ6dET -c /config -p /data --music-dir /data --skip-existing" +``` + +[crontab.guru](https://crontab.guru/) could be used to help with the scheduling expression. \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..774b625 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +services: + sldl: + build: + context: . + environment: + - TZ=Etc/GMT # Specify timezone from TZ Database name found here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + #- PUID=1000 # recommended if running docker on linux host, see main README Docker setup instructions + #- PGID=1000 # recommended if running docker on linux host, see main README Docker setup instructions + volumes: + - ./config:/config + - ./data:/data \ No newline at end of file diff --git a/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/dependencies.d/init-mod-universal-crontab-config b/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/dependencies.d/init-mod-universal-crontab-config new file mode 100644 index 0000000..e69de29 diff --git a/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/run b/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/run new file mode 100755 index 0000000..075a118 --- /dev/null +++ b/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/run @@ -0,0 +1,4 @@ +#!/usr/bin/with-contenv bash + +echo -e "\nStarting cron" +/usr/sbin/crond -b -S -l 0 -L /config/cron.log \ No newline at end of file diff --git a/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/type b/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/type new file mode 100644 index 0000000..3d92b15 --- /dev/null +++ b/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/up b/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/up new file mode 100644 index 0000000..bb88ca2 --- /dev/null +++ b/docker/root/etc/s6-overlay/s6-rc.d/svc-cron/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/svc-cron/run diff --git a/docker/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-cron b/docker/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-cron new file mode 100644 index 0000000..e69de29