mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-09-17 07:09:09 +02:00
Refactor Dockerfile to improve clarity and efficiency
Removed comments and streamlined the Dockerfile for clarity. Adjusted package installations and added healthcheck configurations.
This commit is contained in:
@@ -1,270 +1,28 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
#============================#
|
#============================#
|
||||||
# ALEXBELGIUM'S DOCKERFILE #
|
# ALEXBELGIUM'S DOCKERFILE #
|
||||||
# BirdNET-Go (OpenVINO/AMD64)#
|
|
||||||
#============================#
|
#============================#
|
||||||
# _.------.
|
# _.------.
|
||||||
# _.-` ('>.-`"""-.
|
# _.-` ('>.-`"""-.
|
||||||
# '.--'` _'` _ .--.)
|
# '.--'` _'` _ .--.)
|
||||||
# -' '-.-';` `
|
# -' '-.-';` `
|
||||||
# ' - _.' ``'--.
|
# ' - _.' ``'--.
|
||||||
# '---` .-'""``
|
# '---` .-'""`
|
||||||
# /`
|
# /`
|
||||||
#=== Home Assistant Addon ===#
|
#=== 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/onnxruntime versions, task names)
|
|
||||||
# sync them here.
|
|
||||||
|
|
||||||
##########################################################
|
#################
|
||||||
# 0 Prepare merged BirdNET-Go source tree (fork + PRs) #
|
# 1 Build Image #
|
||||||
##########################################################
|
#################
|
||||||
|
|
||||||
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
|
ARG BUILD_VERSION
|
||||||
ENV BUILD_VERSION=${BUILD_VERSION:-unknown}
|
ARG BUILD_FROM
|
||||||
|
FROM ${BUILD_FROM}
|
||||||
# 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"]
|
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}
|
|
||||||
ARG ONNXRUNTIME_VERSION=1.25.1
|
|
||||||
|
|
||||||
# Download ONNX Runtime for amd64 (x64)
|
|
||||||
RUN 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 #
|
# 2 Modify Image #
|
||||||
##################
|
##################
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
||||||
|
|
||||||
# Set S6 wait time
|
# Set S6 wait time
|
||||||
ENV S6_CMD_WAIT_FOR_SERVICES=1 \
|
ENV S6_CMD_WAIT_FOR_SERVICES=1 \
|
||||||
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
||||||
@@ -304,7 +62,7 @@ COPY ha_automodules.sh /ha_automodules.sh
|
|||||||
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
|
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
|
||||||
|
|
||||||
# Manual apps
|
# Manual apps
|
||||||
ENV PACKAGES="alsa-utils libasound2-plugins mariadb-client nginx yq"
|
ENV PACKAGES="alsa-utils libasound2-plugins nginx yq"
|
||||||
|
|
||||||
# Automatic apps & bashio
|
# Automatic apps & bashio
|
||||||
COPY ha_autoapps.sh /ha_autoapps.sh
|
COPY ha_autoapps.sh /ha_autoapps.sh
|
||||||
@@ -363,3 +121,19 @@ LABEL \
|
|||||||
#################
|
#################
|
||||||
# 6 Healthcheck #
|
# 6 Healthcheck #
|
||||||
#################
|
#################
|
||||||
|
|
||||||
|
# Avoid spamming logs
|
||||||
|
# hadolint ignore=SC2016
|
||||||
|
RUN \
|
||||||
|
# Handle Apache configuration
|
||||||
|
if [ -d /etc/apache2/sites-available ]; then \
|
||||||
|
for file in /etc/apache2/sites-*/*.conf; do \
|
||||||
|
sed -i '/<VirtualHost/a \ \n # Match requests with the custom User-Agent "HealthCheck" \n SetEnvIf User-Agent "HealthCheck" dontlog \n # Exclude matching requests from access logs \n CustomLog ${APACHE_LOG_DIR}/access.log combined env=!dontlog' "$file"; \
|
||||||
|
done; \
|
||||||
|
fi && \
|
||||||
|
\
|
||||||
|
# Handle Nginx configuration
|
||||||
|
if [ -f /etc/nginx/nginx.conf ]; then \
|
||||||
|
awk '/http \{/{print; print "map $http_user_agent $dontlog {\n default 0;\n \"~*HealthCheck\" 1;\n}\naccess_log /var/log/nginx/access.log combined if=$dontlog;"; next}1' /etc/nginx/nginx.conf > /etc/nginx/nginx.conf.new && \
|
||||||
|
mv /etc/nginx/nginx.conf.new /etc/nginx/nginx.conf; \
|
||||||
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user