mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-11-04 03:42:14 +00:00
The bundled ORT must match the onnxruntime_go binding the merged source compiles against; upstream moves both together in its own Dockerfile ARG. Reading it from the merged tree removes the separate pin that went stale in 20261102.1 (ORT 1.25.1 vs binding requesting API 29). Co-authored-by: BirdNET-Go Addon Builder <addon-builder@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
372 lines
15 KiB
Docker
372 lines
15 KiB
Docker
# syntax=docker/dockerfile:1
|
|
#============================#
|
|
# ALEXBELGIUM'S DOCKERFILE #
|
|
# BirdNET-Go (OpenVINO/AMD64)#
|
|
#============================#
|
|
# _.------.
|
|
# _.-` ('>.-`"""-.
|
|
# '.--'` _'` _ .--.)
|
|
# -' '-.-';` `
|
|
# ' - _.' ``'--.
|
|
# '---` .-'""``
|
|
# /`
|
|
#=== Home Assistant Addon ===#
|
|
#
|
|
# AMD64-only, OpenVINO-enabled build of the BirdNET-Go add-on.
|
|
# The binary is compiled from the alexbelgium/birdnet-go fork with the
|
|
# OpenVINO inference backend enabled (openvino build tag). The OpenVINO
|
|
# 2026.2 runtime libraries are bundled in the image, enabling:
|
|
# - Faster CPU inference on modern Intel CPUs (AVX-512/AMX)
|
|
# - Intel iGPU inference when /dev/dri is passed from the host
|
|
#
|
|
# Before compiling, "merge-prs.sh" clones the fork, fast-forwards its main
|
|
# onto the tphakala/birdnet-go upstream and merges every OPEN, NON-DRAFT
|
|
# pull request on the fly. Home Assistant integration layers (2-6) are then
|
|
# applied on top and are byte-for-byte identical to the upstream variant.
|
|
#
|
|
# Build stages 0-1 mirror tphakala/birdnet-go's Docker/Dockerfile; if
|
|
# upstream changes its build (Go/Node versions, task names) sync them
|
|
# here. The ONNX Runtime version is read from upstream's Dockerfile.
|
|
|
|
##########################################################
|
|
# 0 Prepare merged BirdNET-Go source tree (fork + PRs) #
|
|
##########################################################
|
|
|
|
FROM alpine/git:latest AS birdnet-source
|
|
ARG BIRDNET_FORK=alexbelgium/birdnet-go
|
|
ARG BIRDNET_UPSTREAM=tphakala/birdnet-go
|
|
# BUILD_DATE changes on every CI run, busting this layer's cache so the fork is
|
|
# re-cloned and the open PRs are re-merged "on the fly" on every build.
|
|
ARG BUILD_DATE=unknown
|
|
RUN apk add --no-cache bash curl jq
|
|
COPY merge-prs.sh /usr/local/bin/merge-prs.sh
|
|
RUN chmod +x /usr/local/bin/merge-prs.sh && \
|
|
echo "Build date marker: ${BUILD_DATE}" && \
|
|
BIRDNET_FORK="${BIRDNET_FORK}" BIRDNET_UPSTREAM="${BIRDNET_UPSTREAM}" \
|
|
/usr/local/bin/merge-prs.sh /birdnet-src
|
|
|
|
##########################################################
|
|
# 0b Download OpenVINO runtime libraries for amd64 #
|
|
##########################################################
|
|
|
|
FROM alpine:3 AS openvino-libs
|
|
ARG OPENVINO_BUILD=2026.2.0.21903.52ddc073857
|
|
ARG OPENVINO_RELEASE=2026.2
|
|
|
|
# Download the x86_64 OpenVINO runtime package and extract runtime/lib/intel64.
|
|
# The same build id is used for the C API headers downloaded during compilation
|
|
# (see Taskfile.yml OPENVINO_BUILD), ensuring header/runtime version parity.
|
|
# We use the arm64 package for headers (arch-independent C declarations) but the
|
|
# x86_64 package here for the actual runtime .so files.
|
|
#
|
|
# OpenVINO links against its own bundled oneTBB (libtbb.so.12, libtbbmalloc*),
|
|
# which does NOT live in runtime/lib/intel64 but in runtime/3rdparty/tbb/lib.
|
|
# It must be bundled too, otherwise dlopen("libopenvino_c.so") fails at runtime
|
|
# with "libtbb.so.12: cannot open shared object file: No such file or directory"
|
|
# and the OpenVINO backend silently falls back / GPU planning treats the device
|
|
# as unavailable.
|
|
RUN apk add --no-cache curl && \
|
|
mkdir -p /openvino && \
|
|
curl -fsSL \
|
|
"https://storage.openvinotoolkit.org/repositories/openvino/packages/${OPENVINO_RELEASE}/linux/openvino_toolkit_ubuntu22_${OPENVINO_BUILD}_x86_64.tgz" \
|
|
-o /tmp/openvino.tgz && \
|
|
tar -xzf /tmp/openvino.tgz -C /tmp/ --strip-components=1 && \
|
|
cd /tmp/runtime/lib/intel64 && \
|
|
tar -cf - . | tar -xf - -C /openvino/ && \
|
|
# Bundle OpenVINO's own oneTBB runtime (preserving symlinks with cp -a).
|
|
# Search the whole 3rdparty tree so the copy survives minor layout changes
|
|
# between OpenVINO releases. Fail the build loudly if libtbb is missing,
|
|
# since the runtime is unusable without it.
|
|
find /tmp/runtime/3rdparty -name 'libtbb*.so*' -exec cp -a {} /openvino/ \; && \
|
|
if ! ls /openvino/libtbb.so.12* >/dev/null 2>&1; then \
|
|
echo "ERROR: libtbb.so.12 not found in OpenVINO package 3rdparty/tbb" >&2; \
|
|
exit 1; \
|
|
fi && \
|
|
rm -rf /tmp/openvino.tgz /tmp/runtime /tmp/tools /tmp/python \
|
|
/tmp/samples /tmp/install_dependencies 2>/dev/null || true
|
|
|
|
#########################################################################
|
|
# 1a Build environment (mirrors tphakala/birdnet-go Docker/Dockerfile) #
|
|
#########################################################################
|
|
|
|
FROM --platform=$BUILDPLATFORM golang:1.27-trixie AS buildenv
|
|
ARG BUILD_VERSION
|
|
ENV BUILD_VERSION=${BUILD_VERSION:-unknown}
|
|
|
|
# Install Task and other dependencies
|
|
RUN apt-get update -q && apt-get install -q -y \
|
|
curl \
|
|
git \
|
|
sudo \
|
|
zip \
|
|
gcc-aarch64-linux-gnu && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install Node.js v24 from NodeSource
|
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && \
|
|
apt-get install -y nodejs && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install Task
|
|
RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
|
|
|
|
# Create dev-user for building
|
|
RUN groupadd --gid 10001 dev-user && \
|
|
useradd --uid 10001 --gid dev-user --shell /bin/bash --create-home dev-user && \
|
|
usermod -aG sudo dev-user && \
|
|
usermod -aG audio dev-user && \
|
|
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \
|
|
mkdir -p /home/dev-user/src && \
|
|
mkdir -p /home/dev-user/lib && \
|
|
mkdir -p /home/dev-user/.cache && \
|
|
mkdir -p /home/dev-user/.npm && \
|
|
chown -R dev-user:dev-user /home/dev-user
|
|
|
|
USER dev-user
|
|
WORKDIR /home/dev-user/src/BirdNET-Go
|
|
|
|
# Bring in the merged source tree (fork main + upstream sync + open PRs)
|
|
COPY --from=birdnet-source --chown=dev-user /birdnet-src ./
|
|
|
|
# Pre-build frontend once in the shared buildenv stage
|
|
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
RUN task frontend-build
|
|
|
|
##################
|
|
# 1b Build stage #
|
|
##################
|
|
|
|
FROM --platform=$BUILDPLATFORM buildenv AS build
|
|
ARG BUILD_VERSION
|
|
ENV BUILD_VERSION=${BUILD_VERSION:-unknown}
|
|
|
|
# Download ONNX Runtime for amd64 (x64). The version is read from upstream's own
|
|
# Dockerfile in the merged source tree, so it always matches the onnxruntime_go
|
|
# binding this source is compiled against (upstream moves both together).
|
|
RUN ONNXRUNTIME_VERSION="$(sed -n 's/^ARG ONNXRUNTIME_VERSION=//p' Dockerfile)" && \
|
|
if [ -z "${ONNXRUNTIME_VERSION}" ]; then \
|
|
echo "ERROR: ARG ONNXRUNTIME_VERSION not found in upstream Dockerfile" >&2; \
|
|
exit 1; \
|
|
fi && \
|
|
echo "Downloading ONNX Runtime ${ONNXRUNTIME_VERSION} for x64" && \
|
|
curl -fsSL "https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz" \
|
|
-o /tmp/onnxruntime.tgz && \
|
|
mkdir -p /tmp/onnxruntime && \
|
|
tar -xzf /tmp/onnxruntime.tgz -C /tmp/onnxruntime --strip-components=1 && \
|
|
cp /tmp/onnxruntime/lib/libonnxruntime*.so* /home/dev-user/lib/ && \
|
|
rm -rf /tmp/onnxruntime /tmp/onnxruntime.tgz
|
|
|
|
# Build BirdNET-Go for amd64 with OpenVINO enabled.
|
|
# OPENVINO=true compiles in the openvino build tag, enabling the OpenVINO
|
|
# inference backend (dlopen'd at runtime; falls back to ONNX Runtime when
|
|
# libopenvino_c.so is absent). The noembed_linux_amd64 task defaults to
|
|
# OPENVINO=true anyway; we make it explicit here for clarity.
|
|
RUN --mount=type=cache,target=/go/pkg/mod,uid=10001,gid=10001 \
|
|
--mount=type=cache,target=/home/dev-user/.cache/go-build,uid=10001,gid=10001 \
|
|
task check-tensorflow && \
|
|
echo "Building amd64 with OpenVINO enabled, BUILD_VERSION=${BUILD_VERSION}" && \
|
|
BUILD_VERSION="${BUILD_VERSION}" DOCKER_LIB_DIR=/home/dev-user/lib task noembed_linux_amd64 OPENVINO=true
|
|
|
|
#####################################################
|
|
# 1c BirdNET-Go runtime base (mirrors upstream) #
|
|
#####################################################
|
|
|
|
FROM debian:trixie-slim AS birdnet-runtime
|
|
|
|
# Copy TFLite model files (amd64 uses TFLite; OpenVINO reads them via its
|
|
# TFLite frontend plugin bundled in the OpenVINO runtime below)
|
|
RUN mkdir -p /models
|
|
COPY --from=build /home/dev-user/src/BirdNET-Go/internal/classifier/data/*.tflite /models/
|
|
RUN chmod -R a+r /models/*.tflite 2>/dev/null || true && \
|
|
chmod a+x /models
|
|
|
|
# Install ALSA library, SOX for audio processing, and system utilities.
|
|
# ocl-icd-libopencl1 provides the OpenCL ICD loader; combined with
|
|
# /dev/dri passthrough from the host it enables Intel iGPU inference.
|
|
RUN apt-get update -q && apt-get install -q -y --no-install-recommends \
|
|
adduser \
|
|
ca-certificates \
|
|
libasound2 \
|
|
ffmpeg \
|
|
sox \
|
|
libsox-fmt-mp3 \
|
|
procps \
|
|
iproute2 \
|
|
net-tools \
|
|
curl \
|
|
wget \
|
|
nano \
|
|
vim \
|
|
less \
|
|
tzdata \
|
|
tzdata-legacy \
|
|
jq \
|
|
strace \
|
|
lsof \
|
|
bash-completion \
|
|
gosu \
|
|
ocl-icd-libopencl1 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Copy TensorFlow Lite library from build stage
|
|
COPY --from=build /home/dev-user/lib/libtensorflowlite_c.so* /usr/lib/
|
|
|
|
# Copy ONNX Runtime libraries from build stage
|
|
COPY --from=build /home/dev-user/lib/libonnxruntime*.so* /usr/lib/
|
|
|
|
# Copy OpenVINO runtime libraries (libopenvino_c.so, CPU/GPU plugins,
|
|
# TFLite frontend, plugins.xml, bundled oneTBB libtbb.so.12, etc.) into a
|
|
# dedicated directory and register it with ldconfig so both
|
|
# dlopen("libopenvino_c.so") and its libtbb.so.12 dependency resolve.
|
|
# plugins.xml is co-located with libopenvino.so so device plugin
|
|
# discovery works without additional environment variables.
|
|
COPY --from=openvino-libs /openvino/ /usr/lib/openvino/
|
|
RUN echo "/usr/lib/openvino" > /etc/ld.so.conf.d/openvino.conf && ldconfig
|
|
|
|
# Include reset_auth tool from build stage
|
|
COPY --from=build /home/dev-user/src/BirdNET-Go/reset_auth.sh /usr/bin/
|
|
RUN chmod +x /usr/bin/reset_auth.sh
|
|
|
|
# Add entrypoint and startup wrapper scripts from build stage
|
|
COPY --from=build /home/dev-user/src/BirdNET-Go/Docker/entrypoint.sh /usr/bin/
|
|
RUN chmod +x /usr/bin/entrypoint.sh
|
|
COPY --from=build /home/dev-user/src/BirdNET-Go/Docker/startup-wrapper.sh /usr/bin/
|
|
RUN chmod +x /usr/bin/startup-wrapper.sh
|
|
|
|
# Create config and data directories with proper permissions for rootless compatibility
|
|
RUN mkdir -p /config /data/clips /data/models && \
|
|
chmod 777 /config /data /data/clips /data/models
|
|
|
|
# Install the freshly built BirdNET-Go binary
|
|
COPY --from=build /home/dev-user/src/BirdNET-Go/bin /usr/bin/
|
|
|
|
# Enable openvino
|
|
ARG NEO_VERSION=26.22.38646.4
|
|
ARG IGC_VERSION=2.36.3+21719
|
|
RUN groupadd -g 109 render || true && \
|
|
usermod -aG render root && \
|
|
\
|
|
apt-get update -q && apt-get install -q -y --no-install-recommends wget ocl-icd-libopencl1 libdrm2 libdrm-intel1 && \
|
|
mkdir -p /tmp/neo && cd /tmp/neo && \
|
|
wget -q https://github.com/intel/intel-graphics-compiler/releases/download/v2.36.3/intel-igc-core-2_${IGC_VERSION}_amd64.deb \
|
|
https://github.com/intel/intel-graphics-compiler/releases/download/v2.36.3/intel-igc-opencl-2_${IGC_VERSION}_amd64.deb \
|
|
https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/intel-opencl-icd_${NEO_VERSION}-0_amd64.deb \
|
|
https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/libigdgmm12_22.10.0_amd64.deb \
|
|
https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/libze-intel-gpu1_${NEO_VERSION}-0_amd64.deb && \
|
|
dpkg -i *.deb && \
|
|
rm -rf /tmp/neo && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
#============================================================================#
|
|
# From here on, the Home Assistant integration layers are identical to the #
|
|
# standard alexbelgium/birdnet-go add-on (which builds FROM the prebuilt #
|
|
# upstream image). The only difference above is that the base is compiled #
|
|
# from the fork + open PRs with OpenVINO enabled. #
|
|
#============================================================================#
|
|
|
|
##################
|
|
# 2 Modify Image #
|
|
##################
|
|
|
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
|
|
# Set S6 wait time
|
|
ENV S6_CMD_WAIT_FOR_SERVICES=1 \
|
|
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
|
S6_SERVICES_GRACETIME=0
|
|
|
|
##################
|
|
# 3 Install apps #
|
|
##################
|
|
|
|
# Add rootfs
|
|
COPY rootfs/ /
|
|
RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -exec chmod +x {} \;
|
|
|
|
# Silence "chmod: Read-only file system" noise from upstream entrypoint:
|
|
# Home Assistant mounts /dev/snd read-only, so the chmod is a no-op and the
|
|
# stderr output is just noise. The "|| true" already absorbs the exit code.
|
|
# Warn (without failing the build) if the upstream pattern drifts so we notice
|
|
# in CI logs and can update the patch.
|
|
RUN if [ -f /usr/bin/entrypoint.sh ]; then \
|
|
if grep -q 'chmod -R a+rw /dev/snd || true' /usr/bin/entrypoint.sh; then \
|
|
sed -i 's#chmod -R a+rw /dev/snd || true#chmod -R a+rw /dev/snd 2>/dev/null || true#' /usr/bin/entrypoint.sh; \
|
|
else \
|
|
echo "WARN: upstream entrypoint.sh /dev/snd chmod pattern not found; nightly drift?" >&2; \
|
|
fi; \
|
|
fi
|
|
|
|
# Uses /bin for compatibility purposes
|
|
# hadolint ignore=DL4005
|
|
RUN if [ ! -f /bin/sh ] && [ -f /usr/bin/sh ]; then ln -s /usr/bin/sh /bin/sh; fi && \
|
|
if [ ! -f /bin/bash ] && [ -f /usr/bin/bash ]; then ln -s /usr/bin/bash /bin/bash; fi
|
|
|
|
# Modules
|
|
ARG MODULES="00-local_mounts.sh 00-smb_mounts.sh"
|
|
|
|
# Automatic modules download
|
|
COPY ha_automodules.sh /ha_automodules.sh
|
|
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
|
|
|
|
# Manual apps
|
|
ENV PACKAGES="alsa-utils libasound2-plugins mariadb-client nginx yq"
|
|
|
|
# Automatic apps & bashio
|
|
COPY ha_autoapps.sh /ha_autoapps.sh
|
|
RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh
|
|
|
|
################
|
|
# 4 Entrypoint #
|
|
################
|
|
|
|
# Add entrypoint
|
|
ENV S6_STAGE2_HOOK=/ha_entrypoint.sh
|
|
COPY ha_entrypoint.sh /ha_entrypoint.sh
|
|
RUN chmod 777 /ha_entrypoint.sh
|
|
|
|
# Install bashio
|
|
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
|
|
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
|
|
|
|
# Avoid config.yaml interference
|
|
RUN sed -i "s|config.yaml|config_env.yaml|g" /etc/cont-init.d/01-config_yaml.sh
|
|
ENTRYPOINT [ "/usr/bin/env" ]
|
|
CMD [ "/ha_entrypoint.sh" ]
|
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
|
|
############
|
|
# 5 Labels #
|
|
############
|
|
|
|
ARG BUILD_ARCH
|
|
ARG BUILD_DATE
|
|
ARG BUILD_DESCRIPTION
|
|
ARG BUILD_NAME
|
|
ARG BUILD_REF
|
|
ARG BUILD_REPOSITORY
|
|
ARG BUILD_VERSION
|
|
ENV BUILD_VERSION="${BUILD_VERSION}"
|
|
LABEL \
|
|
io.hass.name="${BUILD_NAME}" \
|
|
io.hass.description="${BUILD_DESCRIPTION}" \
|
|
io.hass.arch="${BUILD_ARCH}" \
|
|
io.hass.type="addon" \
|
|
io.hass.version=${BUILD_VERSION} \
|
|
maintainer="alexbelgium (https://github.com/alexbelgium)" \
|
|
org.opencontainers.image.title="${BUILD_NAME}" \
|
|
org.opencontainers.image.description="${BUILD_DESCRIPTION}" \
|
|
org.opencontainers.image.vendor="Home Assistant Add-ons" \
|
|
org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \
|
|
org.opencontainers.image.licenses="MIT" \
|
|
org.opencontainers.image.url="https://github.com/alexbelgium" \
|
|
org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \
|
|
org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \
|
|
org.opencontainers.image.created=${BUILD_DATE} \
|
|
org.opencontainers.image.revision=${BUILD_REF} \
|
|
org.opencontainers.image.version=${BUILD_VERSION}
|
|
|
|
#################
|
|
# 6 Healthcheck #
|
|
#################
|