chore(docker): Build Recyclarr inside Dockerfile

For easier integration into docker buildx, Recyclarr is now built inside
of the Dockerfile as a dedicated build stage. This simplified the CI
workflows and local testing a bit.

The changes for this new process were driven by Microsoft's recommended
approach to building .NET applications inside Docker, which is
documented here:

https://github.com/dotnet/dotnet-docker/blob/main/samples/README.md
refit
Robert Dailey 4 weeks ago
parent c6fe122d84
commit 2f7ca477b9

@ -0,0 +1,26 @@
# directories
.config/
.github/
.idea/
.sonarqube/
.vs/
ci/
.vscode/
publish/
schemas/
scripts/
tests/
# csharp output directories
**/bin/
**/obj/
**/out/
# files
Dockerfile*
**/*.trx
**/*.md
# Ignore these directories inside the docker subdir
docker/config/
docker/artifacts/

@ -63,20 +63,6 @@ jobs:
platform: macos-latest
runtime: ${{ matrix.runtime }}
#############################################
build-musl:
name: Build MUSL
secrets: inherit
uses: ./.github/workflows/reusable-build.yml
strategy:
matrix:
runtime: [linux-musl-x64, linux-musl-arm, linux-musl-arm64]
with:
platform: ubuntu-latest
runtime: ${{ matrix.runtime }}
publish-args: -NoSingleFile
skip-test: true
#############################################
codesign:
name: Apple Signing
@ -139,7 +125,7 @@ jobs:
#############################################
docker:
name: Docker
needs: [build-musl]
needs: [build-win, build-linux, build-osx]
uses: ./.github/workflows/reusable-docker.yml
secrets: inherit
@ -211,7 +197,6 @@ jobs:
- build-win
- build-linux
- build-osx
- build-musl
- codesign
- docker
- release

@ -51,11 +51,6 @@ jobs:
${{ env.semver }},${{ env.prod }},pattern={{major}}.{{minor}}
${{ env.semver }},${{ env.prod }},pattern={{major}}
- name: Grab Artifacts
uses: ./.github/actions/download-tar
with:
path: docker/artifacts
- name: Login to Docker Hub
if: env.SHOULD_PUBLISH == 'true'
uses: docker/login-action@v3
@ -74,7 +69,7 @@ jobs:
- name: Build & Push Image
uses: docker/build-push-action@v5
with:
context: ./docker
context: .
push: ${{ env.SHOULD_PUBLISH == 'true' }}
no-cache: true
platforms: linux/arm/v7,linux/arm64,linux/amd64

@ -0,0 +1,48 @@
# syntax=docker/dockerfile:1.7-labs
# Following Microsoft's pattern shown here:
# https://github.com/dotnet/dotnet-docker/blob/main/samples/dotnetapp/Dockerfile.alpine
# https://github.com/dotnet/dotnet-docker/blob/main/samples/README.md
#
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
ARG TARGETARCH
WORKDIR /source
# copy csproj and restore as distinct layers. Typically, packages change less often than code, so
# this cached layer is expected to be reused in the majority of cases.
#
# NOTE: --parents requires dockerfile version 1.7-labs since it isn't released yet. More info here:
# https://docs.docker.com/build/dockerfile/release-notes/#170
COPY --parents *.props src/*/*.csproj ./
RUN dotnet restore src/Recyclarr.Cli -a $TARGETARCH
# copy and publish app and libraries
COPY . .
RUN dotnet publish src/Recyclarr.Cli -a $TARGETARCH --no-restore -o /app
# Enable globalization and time zones:
# https://github.com/dotnet/dotnet-docker/blob/main/samples/enable-globalization.md
# final stage/image
FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine
# Read below for the reasons why COMPlus_EnableDiagnostics is set:
# https://github.com/dotnet/docs/issues/10217
# https://github.com/dotnet/runtime/issues/96227
ENV PATH="${PATH}:/app/recyclarr" \
RECYCLARR_APP_DATA=/config \
CRON_SCHEDULE="@daily" \
RECYCLARR_CREATE_CONFIG=false \
COMPlus_EnableDiagnostics=0
RUN set -ex; \
apk add --no-cache bash tzdata supercronic git tini; \
mkdir -p /config && chown 1000:1000 /config;
COPY --from=build /app /app/recyclarr/
COPY --chmod=555 ./docker/scripts/prod/*.sh /
USER 1000:1000
VOLUME /config
ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"]

@ -1,20 +1,26 @@
name: recyclarr
networks:
recyclarr:
name: recyclarr_dev
external: true
services:
recyclarr:
app:
image: ghcr.io/recyclarr/recyclarr:edge
user: $DOCKER_UID:$DOCKER_GID
container_name: recyclarr
read_only: true
tmpfs: /tmp
build:
context: .
args:
- TARGETARCH=amd64
# platforms:
# - linux/arm/v7
# - linux/arm64
# - linux/amd64
networks: [recyclarr]
volumes:
- ./config:/config
- ./docker/config:/config
environment:
CRON_SCHEDULE: "* * * * *"
TZ: America/Chicago

@ -1,48 +0,0 @@
[CmdletBinding()]
param (
[string] $Runtime = "linux-musl-x64",
[string[]] $RunArgs
)
$ErrorActionPreference = "Stop"
$artifactsDir = "$PSScriptRoot\artifacts"
# Delete old build artifacts
Remove-Item $artifactsDir -Recurse -Force -ErrorAction SilentlyContinue
# Publish new build artifacts
Push-Location $PSScriptRoot\..
try {
& .\ci\Publish.ps1 -NoSingleFile `
-OutputDir "$artifactsDir\$Runtime" `
-Runtime $Runtime
}
finally {
Pop-Location
}
# Start the corresponding radarr/sonarr docker containers for testing/debugging
Push-Location "$PSScriptRoot\..\debugging"
try {
docker compose up -d --pull always
if ($LASTEXITCODE -ne 0) {
throw "docker compose up failed"
}
}
finally {
Pop-Location
}
# Finally, build the docker image and run it
docker compose build
if ($LASTEXITCODE -ne 0) {
throw "docker compose build failed"
}
# TODO: Use `--build` when it releases:
# https://github.com/docker/compose/issues/10003
docker compose run --rm recyclarr @RunArgs
if ($LASTEXITCODE -ne 0) {
throw "docker compose run failed"
}

@ -0,0 +1,15 @@
$ErrorActionPreference = "Stop"
$debuggingYaml = "$PSScriptRoot/debugging/docker-compose.yml"
$recyclarrYaml = "$PSScriptRoot/../docker-compose.yml"
# Start the corresponding radarr/sonarr docker containers for testing/debugging
docker compose -f $debuggingYaml up -d --pull always
if ($LASTEXITCODE -ne 0) {
throw "docker compose up failed"
}
docker compose -f $recyclarrYaml run --rm --build app @args
if ($LASTEXITCODE -ne 0) {
throw "docker compose run failed"
}

@ -1,31 +0,0 @@
FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine as base
FROM base AS base-arm
ENV RUNTIME=linux-musl-arm
FROM base AS base-arm64
ENV RUNTIME=linux-musl-arm64
FROM base AS base-amd64
ENV RUNTIME=linux-musl-x64
FROM base-$TARGETARCH AS final
# Required by environment and/or dotnet
ENV PATH="${PATH}:/app/recyclarr" \
RECYCLARR_APP_DATA=/config \
CRON_SCHEDULE="@daily" \
RECYCLARR_CREATE_CONFIG=false \
COMPlus_EnableDiagnostics=0
RUN set -ex; \
apk add --no-cache bash tzdata supercronic git tini; \
mkdir -p /config && chown 1000:1000 /config;
COPY ./artifacts/$RUNTIME /app/recyclarr/
COPY --chmod=555 ./scripts/prod/*.sh /
USER 1000:1000
VOLUME /config
ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"]
Loading…
Cancel
Save