From 143bb634f07a0fb274f313f51ca6a04f1e25cee1 Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Sat, 14 May 2022 10:28:51 -0500 Subject: [PATCH] feat: Docker support --- .github/workflows/docker.yml | 60 ++++++++++++++++++++++++++++++++++++ CHANGELOG.md | 7 +++++ debugging/docker-compose.yml | 19 ++++++++++-- docker/.gitignore | 1 + docker/Dockerfile | 54 ++++++++++++++++++++++++++++++++ docker/docker-compose.yml | 21 +++++++++++++ docker/entrypoint.sh | 28 +++++++++++++++++ 7 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/docker.yml create mode 100644 docker/.gitignore create mode 100644 docker/Dockerfile create mode 100644 docker/docker-compose.yml create mode 100755 docker/entrypoint.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..87ec750b --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,60 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json +name: Docker Image + +on: + push: + paths: + - 'docker/**' + + pull_request: + paths: + - 'docker/**' + + release: + types: [ published ] + +jobs: + docker: + name: Build & Push Docker Image + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Buildx + uses: docker/setup-buildx-action@v1 + + - name: Extract Image Metadata + id: meta + uses: docker/metadata-action@v3 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=semver,pattern={{major}}.{{minor}}.{{patch}},value=${{ github.event.release.tag_name }} + type=semver,pattern={{major}}.{{minor}},value=${{ github.event.release.tag_name }} + type=semver,pattern={{major}},value=${{ github.event.release.tag_name }} + + - name: Login to GHCR + if: github.event_name == 'release' + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build & Push Image + uses: docker/build-push-action@v2 + with: + context: ./docker + push: ${{ github.event_name == 'release' }} + no-cache: true + build-args: | + REPOSITORY=${{ github.repository }} + ${{ github.event.release.tag_name && format('RELEASE_TAG={0}', github.event.release.tag_name) }} + platforms: linux/arm/v7,linux/arm64,linux/amd64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/CHANGELOG.md b/CHANGELOG.md index ae758921..4c33bc17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Docker support! Image name is `ghcr.io/recyclarr/recyclarr`. See the [Docker] wiki page for more + information. + +[Docker]: https://github.com/recyclarr/recyclarr/wiki/Docker + ## [2.1.2] - 2022-05-29 ### Fixed diff --git a/debugging/docker-compose.yml b/debugging/docker-compose.yml index 3fcb8aac..ea928d77 100644 --- a/debugging/docker-compose.yml +++ b/debugging/docker-compose.yml @@ -1,5 +1,9 @@ version: '3' +networks: + recyclarr: + name: recyclarr + volumes: radarr1: radarr2: @@ -8,7 +12,10 @@ volumes: services: radarr1: image: ghcr.io/hotio/radarr - network_mode: bridge + networks: + recyclarr: + aliases: + - radarr1 ports: - 7878:7878 volumes: @@ -19,7 +26,10 @@ services: radarr2: image: ghcr.io/hotio/radarr:nightly - network_mode: bridge + networks: + recyclarr: + aliases: + - radarr2 ports: - 6767:7878 volumes: @@ -29,7 +39,10 @@ services: sonarr1: image: ghcr.io/hotio/sonarr:nightly - network_mode: bridge + networks: + recyclarr: + aliases: + - sonarr1 ports: - 8989:8989 volumes: diff --git a/docker/.gitignore b/docker/.gitignore new file mode 100644 index 00000000..5b8a7b86 --- /dev/null +++ b/docker/.gitignore @@ -0,0 +1 @@ +/config/ diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..3f0092d5 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,54 @@ +FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build + +WORKDIR /build + +ARG RELEASE_TAG=latest +ARG TARGETPLATFORM +ARG REPOSITORY=recyclarr/recyclarr + +RUN apk add unzip + +RUN set -ex; \ + \ + # The download path is a bit different when using the latest release instead of a specific + # release + if [ "$RELEASE_TAG" = "latest" ]; then \ + download_path="latest/download"; \ + else \ + download_path="download/$RELEASE_TAG"; \ + fi; \ + \ + # Determine the runtime from the target platform provided by Docker Buildx + case "$TARGETPLATFORM" in \ + "linux/arm/v7") runtime="linux-musl-arm" ;; \ + "linux/arm64") runtime="linux-musl-arm64" ;; \ + "linux/amd64") runtime="linux-musl-x64" ;; \ + *) echo >&2 "ERROR: Unsupported target platform: $TARGETPLATFORM"; exit 1 ;; \ + esac; \ + \ + # Download and extract the recyclarr binary from the release + wget --quiet -O recyclarr.zip "https://github.com/$REPOSITORY/releases/$download_path/recyclarr-$runtime.zip"; \ + unzip recyclarr.zip; + +############################################################################# +FROM alpine + +# Required by environment and/or dotnet +ENV HOME=/config \ + DOTNET_BUNDLE_EXTRACT_BASE_DIR=/tmp/.net \ + # Environment variables used by the entrypoint script. These may be overridden from `docker run` + # as needed. + CRON_SCHEDULE="@daily" \ + # The GLOBALIZATION variable is so that we do not need libicu installed (saves us ~40MB). + DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true + +VOLUME /config + +RUN set -ex; \ + apk add --no-cache busybox-suid su-exec libstdc++; \ + adduser --disabled-password --home "$HOME" recyclarr; + +COPY --chown=recyclarr:recyclarr --chmod=544 --from=build /build/recyclarr /usr/local/bin +COPY --chown=recyclarr:recyclarr --chmod=544 entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000..e4ef600b --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3' + +networks: + recyclarr: + name: recyclarr + external: true + +services: + recyclarr: + image: ghcr.io/recyclarr/recyclarr + container_name: recyclarr + build: + context: . + args: + - TARGETPLATFORM=linux/amd64 + init: true + networks: [recyclarr] + volumes: + - ./config:/config + environment: + CRON_SCHEDULE: "* * * * *" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 00000000..87b80986 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,28 @@ +#!/bin/sh +set -e + +if [ ! -f "$HOME/recyclarr.yml" ]; then + su-exec recyclarr recyclarr create-config --path "$HOME" +fi + +appdata="--app-data \"$HOME\"" + +# If the script has any arguments, invoke the CLI instead. This allows the image to be used as a CLI +# with something like: +# +# ``` +# docker run --rm -v ./config:/config ghcr.io/recyclarr/recyclarr sonarr +# ``` +# +if [ "$#" -gt 0 ]; then + su-exec recyclarr recyclarr "$@" $appdata +else + echo "Creating crontab file..." + echo "$CRON_SCHEDULE recyclarr sonarr $appdata; recyclarr radarr $appdata" \ + | crontab -u recyclarr - + + crontab -l -u recyclarr + + echo "Starting cron daemon..." + exec crond -f +fi