diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..149fffed6 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,82 @@ +name: docker build + +on: + push: + branches: + - develop + - main + tags: + - v* + +env: + REGISTRY_IMAGE: nzbgetcom/nzbget + +jobs: + build: + runs-on: ubuntu-latest + permissions: + packages: write + + steps: + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Generate image tags + id: gen_tags + run: | + if [[ "$GITHUB_REF_NAME" == "develop" ]]; then + TAG="testing" + fi + if [[ "$GITHUB_REF_NAME" == "main" ]]; then + TAG="latest" + fi + if [[ $GITHUB_REF == 'refs/tags/'* ]]; then + TAG="${GITHUB_REF/refs\/tags\//}" + fi + if [[ "$TAG" == "" ]]; then + TAG="${GITHUB_REF_NAME/\//-}" + fi + TAGS="${{ env.REGISTRY_IMAGE }}:$TAG,ghcr.io/${{ env.REGISTRY_IMAGE }}:$TAG" + echo "tags=$TAGS" >> $GITHUB_OUTPUT + echo "version=$TAG" >> $GITHUB_OUTPUT + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: docker + platforms: linux/amd64,linux/arm64,linux/arm/v7 + provenance: false + push: true + tags: ${{ steps.gen_tags.outputs.tags }} + outputs: "type=image,name=${{ env.REGISTRY_IMAGE }},annotation-index.org.opencontainers.image.description=NZBGet from nzbget.com - version ${{ steps.gen_tags.outputs.version }}" + build-args: | + "NZBGET_RELEASE=${{ github.ref_name }}" + "MAKE_JOBS=2" + + - name: Update Docker Hub Description + uses: peter-evans/dockerhub-description@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: ${{ env.REGISTRY_IMAGE }} + readme-filepath: ./docker/README.md diff --git a/.gitignore b/.gitignore index 3bd6a5cbc..c2921df7b 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,5 @@ code_revision.cpp pytest.ini .cache /.idea +docker/downloads +docker/config diff --git a/README.md b/README.md index 03294e880..14060a270 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![linux build](https://github.com/nzbgetcom/nzbget/actions/workflows/linux.yml/badge.svg?branch=main)](https://github.com/nzbgetcom/nzbget/actions/workflows/linux.yml) [![windows build](https://github.com/nzbgetcom/nzbget/actions/workflows/windows.yml/badge.svg?branch=main)](https://github.com/nzbgetcom/nzbget/actions/workflows/windows.yml) [![osx build](https://github.com/nzbgetcom/nzbget/actions/workflows/osx.yml/badge.svg)](https://github.com/nzbgetcom/nzbget/actions/workflows/osx.yml) +[![docker build](https://github.com/nzbgetcom/nzbget/actions/workflows/docker.yml/badge.svg)](https://github.com/nzbgetcom/nzbget/actions/workflows/docker.yml) ![Contributions welcome](https://img.shields.io/badge/contributions-welcome-blue.svg) @@ -30,6 +31,8 @@ More information available at https://nzbget.com We provide a easy-to-use installer for each platform we support. Please download binaries from our [releases](https://github.com/nzbgetcom/nzbget/tags) page. +We also provide a docker image for popular architectures. [Docker readme](docker/README.md) + ## Building from sources Please follow [instructions](https://nzbget.com/documentation/building-development-version/) on the website diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 000000000..d03d0ca22 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,73 @@ +# build stage +FROM alpine:3.18.4 AS build + +# args +ARG NZBGET_RELEASE=develop +ARG UNRAR_VERSION=6.2.12 +ARG MAKE_JOBS=1 + +RUN \ + echo "**** install build packages ****" && \ + apk add g++ gcc git libxml2-dev libxslt-dev make ncurses-dev openssl-dev curl && \ + echo "**** build nzbget ****" && \ + mkdir -p /app/nzbget && \ + git clone https://github.com/nzbgetcom/nzbget.git nzbget && \ + cd nzbget/ && \ + git checkout ${NZBGET_RELEASE} && \ + ./configure bindir='${exec_prefix}' && \ + make -j ${MAKE_JOBS} && \ + make prefix=/app/nzbget install && \ + sed -i \ + -e "s#^MainDir=.*#MainDir=/downloads#g" \ + -e "s#^ScriptDir=.*#ScriptDir=$\{MainDir\}/scripts#g" \ + -e "s#^WebDir=.*#WebDir=$\{AppDir\}/webui#g" \ + -e "s#^ConfigTemplate=.*#ConfigTemplate=$\{AppDir\}/webui/nzbget.conf.template#g" \ + -e "s#^UnrarCmd=.*#UnrarCmd=$\{AppDir\}/unrar#g" \ + -e "s#^SevenZipCmd=.*#SevenZipCmd=$\{AppDir\}/7za#g" \ + -e "s#^CertStore=.*#CertStore=$\{AppDir\}/cacert.pem#g" \ + -e "s#^CertCheck=.*#CertCheck=yes#g" \ + -e "s#^DestDir=.*#DestDir=$\{MainDir\}/completed#g" \ + -e "s#^InterDir=.*#InterDir=$\{MainDir\}/intermediate#g" \ + -e "s#^LogFile=.*#LogFile=$\{MainDir\}/nzbget.log#g" \ + -e "s#^AuthorizedIP=.*#AuthorizedIP=127.0.0.1#g" \ + /app/nzbget/share/nzbget/nzbget.conf && \ + mv /app/nzbget/share/nzbget/webui /app/nzbget/ && \ + cp /app/nzbget/share/nzbget/nzbget.conf /app/nzbget/webui/nzbget.conf.template && \ + ln -s /usr/bin/7za /app/nzbget/7za && \ + ln -s /usr/bin/unrar /app/nzbget/unrar && \ + cp /nzbget/pubkey.pem /app/nzbget/pubkey.pem && \ + curl -o /app/nzbget/cacert.pem -L "https://curl.se/ca/cacert.pem" && \ + echo "**** install unrar from source ****" && \ + mkdir /tmp/unrar && \ + curl -o /tmp/unrar.tar.gz -L "https://www.rarlab.com/rar/unrarsrc-${UNRAR_VERSION}.tar.gz" && \ + tar xf /tmp/unrar.tar.gz -C /tmp/unrar --strip-components=1 && \ + cd /tmp/unrar && \ + make -j ${MAKE_JOBS} && \ + install -v -m755 unrar /usr/bin + +# runtime stage +FROM alpine:3.18.4 +ARG NZBGET_RELEASE=develop + +# labels +LABEL org.opencontainers.image.description="NZBGet from nzbget.com, version ${NZBGET_RELEASE}" +LABEL org.opencontainers.image.source="https://github.com/nzbgetcom/nzbget" +LABEL maintainer="nzbget@nzbget.com" + +ENV TERM linux +RUN \ + echo "**** install packages ****" && \ + apk add --no-cache --update shadow libxml2 libxslt openssl p7zip python3 && \ + ln -sf /usr/bin/python3 /usr/bin/python && \ + echo "**** cleanup ****" && \ + rm -rf /root/.cache /root/.cargo /tmp/* +COPY --from=build /usr/bin/unrar /usr/bin/unrar +COPY --from=build /app/nzbget/ /app/nzbget/ +ADD entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh && \ + echo "**** create non-root user ****" && \ + adduser -G users -D -u 1000 -h /config -s /bin/sh user && \ + mkdir -p /config && \ + mkdir -p /downloads && \ + chown -R user:users /app /config /downloads +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..de1efd37f --- /dev/null +++ b/docker/README.md @@ -0,0 +1,119 @@ +![NZBGet logo](https://nzbget.com/img/logo.svg) + +# NZBGet builds from [nzbgetcom/nzbget](https://github.com/nzbgetcom/nzbget) repository + +NZBGet is an efficient, open-source Usenet software designed for downloading binary content from Usenet newsgroups. + +# Supported Architectures + +| Architecture +|:- +| x86-64 +| arm64 +| armhf + +# Version Tags + +| Tag | Description +|:-------------|- +| latest | Stable nzbget releases (from `main` repository branch) +| testing | Development nzbget builds (from `develop` repository branch) +| v* | Version-specific release builds (like v22.0 for 22.0 nzbget release) + +# Usage + +[docker-compose](https://docs.docker.com/compose/) (recommended) +``` +--- +version: "2.1" +services: + nzbget: + image: nzbgetcom/nzbget:latest + container_name: nzbget + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/London + - NZBGET_USER=nzbget #optional + - NZBGET_PASS=tegbzn6789 #optional + volumes: + - /path/to/config:/config + - /path/to/downloads:/downloads #optional + ports: + - 6789:6789 + restart: unless-stopped +``` + +[docker cli](https://docs.docker.com/engine/reference/commandline/cli/) +``` +docker run -d \ + --name=nzbget \ + -e PUID=1000 \ + -e PGID=1000 \ + -e TZ=Europe/London \ + -e NZBGET_USER=nzbget `#optional` \ + -e NZBGET_PASS=tegbzn6789 `#optional` \ + -p 6789:6789 \ + -v /path/to/config:/config \ + -v /path/to/downloads:/downloads `#optional` \ + --restart unless-stopped \ + nzbgetcom/nzbget:latest +``` + +# Supported environment variables + +NZBGet container can be configured by passing environment variables to it. This can be done in docker-compose mode by specifying `environment:` and in cli mode by using -e switch. + +| Parameter | Description +|:------------|- +| PUID | UserID (see below) +| PGID | GroupID (see below) +| TZ | Timezone +| NZBGET_USER | User name for web auth +| NZBGET_PASS | Password for web auth + +# User / Group Identifiers + +When using volumes (-v flags) permissions issues can arise between the host OS and the container. To avoid this problem we allow to specify the user PUID and group PGID. + +The example above uses PUID=1000 and PGID=1000. To find the required ids, run `id user`: +``` +$ id user +uid=1000(user) gid=1000(users) groups=1000(users) +``` + +# Building locally + +For development purposes can be used Dockerfile or docker-compose file from official repository (`docker` folder): + +``` +git clone https://github.com/nzbgetcom/nzbget.git +cd docker +docker compose up +-or- +docker build . -t nzbget-local +``` + +Dockerfile supports next build arguments: + +| Argument | Description +|:----------------|- +| NZBGET_RELEASE | Branch name or tag to build from +| UNRAR_VERSION | Unrar version +| MAKE_JOBS | Number of make jobs for speed up build + +# ghcr.io + +Docker images also available on [GitHub](https://github.com/nzbgetcom/nzbget/pkgs/container/nzbget). For use - replace `nzbgetcom/nzbget:TAG` with `ghcr.io/nzbgetcom/nzbget:TAG` in above examples. + +# Python version + +NZBGet docker image bundled with Python 3.11 + +# Troubleshooting max speed issues + +In case a linux image or docker image is slower than expected, here are some tips to increase download speed: + +1. Increase number of server connections (NEWS-SERVERS -> Connections) - default is 8, and 16 and 32 are worth trying +2. For slower machines/hosts - increase article read chunk size from 4 to 64 (CONNECTION -> ArticleReadChunkSize). This is new setting, available only on v22 testing images and planned in v23. + diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 000000000..4a63cc347 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,21 @@ +--- +version: "2.1" +services: + nzbget: + build: + context: . + args: + NZBGET_RELEASE: develop + MAKE_JOBS: 4 + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/London + - NZBGET_USER=admin + - NZBGET_PASS=admin + volumes: + - ./config:/config + - ./downloads:/downloads + ports: + - 6789:6789 + restart: unless-stopped diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 000000000..8c143ce14 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env sh +set -e + +# create downloads if not exist +if [ ! -d /downloads ]; then + mkdir -p /downloads +fi + +# delete lock file if found +if [ -f /downloads/nzbget.lock ]; then + rm /downloads/nzbget.lock +fi + +# create default config if not exist +if [ ! -f /config/nzbget.conf ]; then + cp /app/nzbget/share/nzbget/nzbget.conf /config/nzbget.conf +fi + +# parse env vars to options +OPTIONS="" +if [ ! -z "${NZBGET_USER}" ]; then + OPTIONS="${OPTIONS}-o ControlUsername=${NZBGET_USER} " +fi +if [ ! -z "${NZBGET_PASS}" ]; then + OPTIONS="${OPTIONS}-o ControlPassword=${NZBGET_PASS} " +fi + +# copy default scripts if not exists +mkdir -p /downloads/scripts +for SCRIPT in EMail.py Logger.py; do + if [ ! -f /downloads/scripts/$SCRIPT ]; then + cp /app/nzbget/share/nzbget/scripts/$SCRIPT /downloads/scripts/ + fi +done + +# change userid and groupid +PUID=${PUID:-1000} +PGID=${PGID:-1000} +groupmod -o -g "$PGID" users +usermod -o -u "$PUID" user + +chown -R user:users /config +chown -R user:users /downloads +su -p user -c "/app/nzbget/nzbget -s -c /config/nzbget.conf -o OutputMode=log ${OPTIONS}"