mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-11-06 21:53:02 +03:00
* Add analytics opt-in setting, prompt notice kind, and notice watermarks * Add the analytics report schema * Add the analytics state file * Add the install and hardware analytics collectors * Add the detection analytics collector * Add the cameras analytics collector * Add the features analytics collector * Add the health analytics collector * Build analytics reports from the section collectors * Add the analytics report transport * Send the daily analytics report from the main process * Add the analytics preview API * Generate the analytics schema and check it in CI * Record the image variant in each Dockerfile * Show the analytics preview in telemetry settings * Document anonymous analytics * change wording * fixes * update network requirements docs * adapt analytics to free-form model scenes, split notice counts, and peewee 4 * fixes * change log levels * docstrings * docstrings * honor file-only analytics opt-outs and skip pre-consent notices An opt-out saved through the YAML editor's "Save only" or a hand edit never reached the live config, so reports kept going out under the old install ID until a restart. The reporter now reads telemetry.analytics from the config file when a report is due, validated with TelemetryConfig so yes, on, and 1 still count as consent, and an opt-out there deletes the state file and skips the send. The first report under a new install ID also carried every notice since the counters started, including ones from before the opt-in, so a fresh state file now resets the notice watermarks before the report's snapshot. * take the notice baseline at opt-in instead of the first send The watermark reset ran at the first send attempt, so notices raised between the opt-in and that send, up to 45 minutes after a startup, were absorbed into the reset and never reported. The reporter now writes the new install ID and resets the watermarks as soon as it sees consent without a state file. * report notice counts cumulatively from a database baseline Moving watermarks after each accepted send kept the install ID and the notice baseline out of step: pre-consent notices went out, notices raised before the first send were dropped, and a send that finished after an off/on toggle overwrote the new identity's baseline. health.notices now carries cumulative counts since the install ID was created. Creating an ID copies the lifetime counts into the existing reported_* columns before the state file names it, and nothing is written after a send, so the backend diffs consecutive reports per install ID. * write held notice repeats before the analytics baseline reset Repeats of batched kinds like failed_login wait in memory until the stats emitter flushes them, so a baseline reset taken while some were held left them out, and the next flush counted those pre-opt-in repeats as post-consent. The reset now writes held repeats to the notice history under the same lock before copying the counts. * seed detector inference speed from the first inference The average started at 0 so idle detectors read 0, but that made every detector's speed climb from 0 for its first couple dozen inferences after a start. Detectors now use the same InferenceSpeed helper as enrichments, so the first inference seeds the average and idle detectors still read 0.
391 lines
14 KiB
Docker
391 lines
14 KiB
Docker
# syntax=docker/dockerfile:1.6
|
|
|
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
|
ARG DEBIAN_FRONTEND=noninteractive
|
|
|
|
# Globally set pip break-system-packages option to avoid having to specify it every time
|
|
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
|
|
|
ARG BASE_IMAGE=debian:12
|
|
ARG SLIM_BASE=debian:12-slim
|
|
|
|
# A hook that allows us to inject commands right after the base images
|
|
ARG BASE_HOOK=
|
|
|
|
FROM ${BASE_IMAGE} AS base
|
|
ARG PIP_BREAK_SYSTEM_PACKAGES
|
|
ARG BASE_HOOK
|
|
|
|
RUN sh -c "$BASE_HOOK"
|
|
|
|
FROM --platform=${BUILDPLATFORM} debian:12 AS base_host
|
|
ARG PIP_BREAK_SYSTEM_PACKAGES
|
|
|
|
FROM ${SLIM_BASE} AS slim-base
|
|
ARG PIP_BREAK_SYSTEM_PACKAGES
|
|
ARG BASE_HOOK
|
|
|
|
RUN sh -c "$BASE_HOOK"
|
|
|
|
FROM slim-base AS wget
|
|
ARG DEBIAN_FRONTEND
|
|
RUN apt-get update \
|
|
&& apt-get install -y wget xz-utils \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
WORKDIR /rootfs
|
|
|
|
FROM base AS nginx
|
|
ARG DEBIAN_FRONTEND
|
|
ENV CCACHE_DIR /root/.ccache
|
|
ENV CCACHE_MAXSIZE 2G
|
|
|
|
RUN --mount=type=bind,source=docker/main/build_nginx.sh,target=/deps/build_nginx.sh \
|
|
/deps/build_nginx.sh
|
|
|
|
FROM wget AS sqlite-vec
|
|
ARG DEBIAN_FRONTEND
|
|
|
|
# Build sqlite_vec from source
|
|
COPY docker/main/build_sqlite_vec.sh /deps/build_sqlite_vec.sh
|
|
RUN --mount=type=tmpfs,target=/tmp --mount=type=tmpfs,target=/var/cache/apt \
|
|
--mount=type=bind,source=docker/main/build_sqlite_vec.sh,target=/deps/build_sqlite_vec.sh \
|
|
--mount=type=cache,target=/root/.ccache \
|
|
/deps/build_sqlite_vec.sh
|
|
|
|
# Build intel-media-driver from source against bookworm's system libva so it
|
|
# works with Debian 12's glibc/libstdc++ (pre-built noble/trixie packages
|
|
# require glibc 2.38 which is not available on bookworm).
|
|
FROM base AS intel-media-driver
|
|
ARG DEBIAN_FRONTEND
|
|
RUN --mount=type=bind,source=docker/main/build_intel_media_driver.sh,target=/deps/build_intel_media_driver.sh \
|
|
/deps/build_intel_media_driver.sh
|
|
|
|
FROM wget AS go2rtc
|
|
ARG TARGETARCH
|
|
RUN --mount=type=bind,source=docker/main/install_go2rtc.sh,target=/deps/install_go2rtc.sh \
|
|
/deps/install_go2rtc.sh
|
|
|
|
FROM wget AS tempio
|
|
ARG TARGETARCH
|
|
RUN --mount=type=bind,source=docker/main/install_tempio.sh,target=/deps/install_tempio.sh \
|
|
/deps/install_tempio.sh
|
|
|
|
####
|
|
#
|
|
# OpenVino Support
|
|
#
|
|
# 1. Download and convert a model from Intel's Public Open Model Zoo
|
|
#
|
|
####
|
|
# Download and Convert OpenVino model
|
|
FROM base_host AS ov-converter
|
|
ARG DEBIAN_FRONTEND
|
|
|
|
# Install OpenVINO for model conversion
|
|
COPY docker/main/requirements-ov.txt /requirements-ov.txt
|
|
RUN apt-get -qq update \
|
|
&& apt-get -qq install -y wget python3 python3-distutils \
|
|
&& wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
|
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
|
&& python3 get-pip.py "pip" \
|
|
&& pip3 install -r /requirements-ov.txt
|
|
|
|
# Get OpenVino Model
|
|
RUN --mount=type=bind,source=docker/main/build_ov_model.py,target=/build_ov_model.py \
|
|
mkdir /models && cd /models \
|
|
&& wget http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz \
|
|
&& tar -xvf ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz \
|
|
&& python3 /build_ov_model.py
|
|
|
|
####
|
|
#
|
|
# Coral Compatibility
|
|
#
|
|
# Builds libusb without udev. Needed for synology and other devices with USB coral
|
|
####
|
|
# libUSB - No Udev
|
|
FROM wget as libusb-build
|
|
ARG TARGETARCH
|
|
ARG DEBIAN_FRONTEND
|
|
ENV CCACHE_DIR /root/.ccache
|
|
ENV CCACHE_MAXSIZE 2G
|
|
|
|
# Build libUSB without udev. Needed for Openvino NCS2 support
|
|
WORKDIR /opt
|
|
RUN apt-get update && apt-get install -y unzip build-essential automake libtool ccache pkg-config
|
|
RUN --mount=type=cache,target=/root/.ccache wget -q https://github.com/libusb/libusb/archive/v1.0.26.zip -O v1.0.26.zip && \
|
|
unzip v1.0.26.zip && cd libusb-1.0.26 && \
|
|
./bootstrap.sh && \
|
|
./configure CC='ccache gcc' CCX='ccache g++' --disable-udev --enable-shared && \
|
|
make -j $(nproc --all)
|
|
RUN apt-get update && \
|
|
apt-get install -y --no-install-recommends libusb-1.0-0-dev && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
WORKDIR /opt/libusb-1.0.26/libusb
|
|
RUN /bin/mkdir -p '/usr/local/lib' && \
|
|
/bin/bash ../libtool --mode=install /usr/bin/install -c libusb-1.0.la '/usr/local/lib' && \
|
|
/bin/mkdir -p '/usr/local/include/libusb-1.0' && \
|
|
/usr/bin/install -c -m 644 libusb.h '/usr/local/include/libusb-1.0' && \
|
|
/bin/mkdir -p '/usr/local/lib/pkgconfig' && \
|
|
cd /opt/libusb-1.0.26/ && \
|
|
/usr/bin/install -c -m 644 libusb-1.0.pc '/usr/local/lib/pkgconfig' && \
|
|
ldconfig
|
|
|
|
FROM wget AS models
|
|
|
|
# Get model and labels
|
|
RUN wget -qO edgetpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite
|
|
RUN wget -qO cpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite
|
|
COPY labelmap.txt .
|
|
# Copy OpenVino model
|
|
COPY --from=ov-converter /models/ssdlite_mobilenet_v2.xml openvino-model/
|
|
COPY --from=ov-converter /models/ssdlite_mobilenet_v2.bin openvino-model/
|
|
RUN wget -q https://github.com/openvinotoolkit/open_model_zoo/raw/master/data/dataset_classes/coco_91cl_bkgr.txt -O openvino-model/coco_91cl_bkgr.txt && \
|
|
sed -i 's/truck/car/g' openvino-model/coco_91cl_bkgr.txt
|
|
# Get Audio Model and labels
|
|
RUN wget -qO - https://www.kaggle.com/api/v1/models/google/yamnet/tfLite/classification-tflite/1/download | tar xvz && mv 1.tflite cpu_audio_model.tflite
|
|
COPY audio-labelmap.txt .
|
|
|
|
RUN chmod -R a+rX /rootfs
|
|
|
|
|
|
FROM wget AS s6-overlay
|
|
ARG TARGETARCH
|
|
RUN --mount=type=bind,source=docker/main/install_s6_overlay.sh,target=/deps/install_s6_overlay.sh \
|
|
/deps/install_s6_overlay.sh
|
|
|
|
|
|
FROM base AS wheels
|
|
ARG DEBIAN_FRONTEND
|
|
ARG TARGETARCH
|
|
ARG DEBUG=false
|
|
|
|
# Use a separate container to build wheels to prevent build dependencies in final image
|
|
RUN apt-get -qq update \
|
|
&& apt-get -qq install -y \
|
|
apt-transport-https wget unzip \
|
|
&& apt-get -qq update \
|
|
&& apt-get -qq install -y \
|
|
python3.11 \
|
|
python3.11-dev \
|
|
# opencv dependencies
|
|
build-essential cmake git pkg-config libgtk-3-dev \
|
|
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
|
|
libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev \
|
|
gfortran openexr libatlas-base-dev libssl-dev\
|
|
libtbbmalloc2 libtbb-dev libdc1394-dev libopenexr-dev \
|
|
libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev \
|
|
# sqlite3 dependencies
|
|
tclsh \
|
|
# scipy dependencies
|
|
gcc gfortran libopenblas-dev liblapack-dev && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1
|
|
|
|
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
|
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
|
&& python3 get-pip.py "pip"
|
|
|
|
COPY docker/main/requirements.txt /requirements.txt
|
|
COPY docker/main/requirements-dev.txt /requirements-dev.txt
|
|
|
|
RUN pip3 install -r /requirements.txt
|
|
|
|
# Build pysqlite3 from source
|
|
COPY docker/main/build_pysqlite3.sh /build_pysqlite3.sh
|
|
RUN /build_pysqlite3.sh
|
|
|
|
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
|
RUN pip3 wheel --wheel-dir=/wheels -r /requirements-wheels.txt && \
|
|
if [ "$DEBUG" = "true" ]; then \
|
|
pip3 wheel --wheel-dir=/wheels -r /requirements-dev.txt; \
|
|
fi
|
|
|
|
# Collect deps in a single layer
|
|
FROM scratch AS deps-rootfs
|
|
COPY --from=nginx /usr/local/nginx/ /usr/local/nginx/
|
|
COPY --from=sqlite-vec /usr/local/lib/ /usr/local/lib/
|
|
COPY --from=intel-media-driver /rootfs/ /
|
|
COPY --from=go2rtc /rootfs/ /
|
|
COPY --from=libusb-build /usr/local/lib /usr/local/lib
|
|
COPY --from=tempio /rootfs/ /
|
|
COPY --from=s6-overlay /rootfs/ /
|
|
COPY --from=models /rootfs/ /
|
|
COPY docker/main/rootfs/ /
|
|
|
|
|
|
# Frigate deps (ffmpeg, python, nginx, go2rtc, s6-overlay, etc)
|
|
FROM slim-base AS deps
|
|
LABEL org.opencontainers.image.source="https://github.com/blakeblackshear/frigate"
|
|
|
|
ARG TARGETARCH
|
|
ARG BASE_IMAGE
|
|
|
|
ARG DEBIAN_FRONTEND
|
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
|
|
|
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
|
ENV NVIDIA_VISIBLE_DEVICES=all
|
|
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
|
|
|
# Disable tokenizer parallelism warning
|
|
# https://stackoverflow.com/questions/62691279/how-to-disable-tokenizers-parallelism-true-false-warning/72926996#72926996
|
|
ENV TOKENIZERS_PARALLELISM=true
|
|
# https://github.com/huggingface/transformers/issues/27214
|
|
ENV TRANSFORMERS_NO_ADVISORY_WARNINGS=1
|
|
|
|
# Set OpenCV ffmpeg loglevel to fatal: https://ffmpeg.org/doxygen/trunk/log_8h.html
|
|
ENV OPENCV_FFMPEG_LOGLEVEL=8
|
|
|
|
# Set NumPy to ignore getlimits warning
|
|
ENV PYTHONWARNINGS="ignore:::numpy.core.getlimits"
|
|
|
|
# Set HailoRT to disable logging
|
|
ENV HAILORT_LOGGER_PATH=NONE
|
|
|
|
# TensorFlow C++ logging suppression (must be set before import)
|
|
# TF_CPP_MIN_LOG_LEVEL: 0=all, 1=INFO+, 2=WARNING+, 3=ERROR+ (we use 3 for errors only)
|
|
ENV TF_CPP_MIN_LOG_LEVEL=3
|
|
# Suppress verbose logging from TensorFlow C++ code
|
|
ENV TF_CPP_MIN_VLOG_LEVEL=3
|
|
# Disable oneDNN optimization messages ("optimized with oneDNN...")
|
|
ENV TF_ENABLE_ONEDNN_OPTS=0
|
|
# Suppress AutoGraph verbosity during conversion
|
|
ENV AUTOGRAPH_VERBOSITY=0
|
|
# Google Logging (GLOG) suppression for TensorFlow components
|
|
ENV GLOG_minloglevel=3
|
|
ENV GLOG_logtostderr=0
|
|
|
|
ENV PATH="/usr/local/go2rtc/bin:/usr/local/tempio/bin:/usr/local/nginx/sbin:${PATH}"
|
|
|
|
# Install dependencies
|
|
RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/deps/install_deps.sh \
|
|
/deps/install_deps.sh
|
|
|
|
# Runtime users. frigate may be remapped at start via PUID/PGID (init-usermod)
|
|
# or replaced entirely with docker's --user. go2rtc is intentionally separate
|
|
# and more restricted. frigate-data is the shared group for /config access.
|
|
# -o tolerates variant base images that already contain uid/gid 1000.
|
|
RUN groupadd -o --gid 1000 frigate \
|
|
&& useradd -o --uid 1000 --gid frigate --no-create-home --shell /usr/sbin/nologin frigate \
|
|
&& groupadd --system go2rtc \
|
|
&& useradd --system --gid go2rtc --no-create-home --shell /usr/sbin/nologin go2rtc \
|
|
&& groupadd --system frigate-data \
|
|
&& usermod -aG frigate-data frigate \
|
|
&& usermod -aG frigate-data go2rtc \
|
|
&& for grp in video render plugdev audio; do \
|
|
if getent group "$grp" >/dev/null; then \
|
|
usermod -aG "$grp" frigate && usermod -aG "$grp" go2rtc; \
|
|
fi; \
|
|
done
|
|
|
|
ENV DEFAULT_FFMPEG_VERSION="8.0"
|
|
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:7.0:5.0"
|
|
|
|
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
|
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
|
&& python3 get-pip.py "pip"
|
|
|
|
RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \
|
|
pip3 install -U /deps/wheels/*.whl
|
|
|
|
# The Hailo, MemryX, and Axera runtimes are installed at first start by
|
|
# frigate/util/runtime_deps.py, only when that detector is configured.
|
|
# Axera's native libraries are bind mounted from the host.
|
|
ENV PATH="${PATH}:/usr/bin/axcl"
|
|
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/lib/axcl"
|
|
|
|
COPY --from=deps-rootfs / /
|
|
|
|
RUN ldconfig
|
|
|
|
EXPOSE 5000
|
|
EXPOSE 8554
|
|
EXPOSE 8555/tcp 8555/udp
|
|
|
|
# Configure logging to prepend timestamps, log to stdout, keep 0 archives and rotate on 10MB
|
|
ENV S6_LOGGING_SCRIPT="T 1 n0 s10000000 T"
|
|
# Do not fail on long-running download scripts
|
|
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
|
|
# Allow running with a read-only root filesystem: s6 copies its scan dir into
|
|
# /run and executes service scripts from there, so /run must allow exec
|
|
ENV S6_READ_ONLY_ROOT=1
|
|
|
|
ENTRYPOINT ["/init"]
|
|
CMD []
|
|
|
|
HEALTHCHECK --start-period=300s --start-interval=5s --interval=15s --timeout=5s --retries=3 \
|
|
CMD test -f /dev/shm/.frigate-is-stopping && exit 0; curl --fail --silent --show-error http://127.0.0.1:5000/api/version || exit 1
|
|
|
|
# Frigate deps with Node.js and NPM for devcontainer
|
|
FROM deps AS devcontainer
|
|
|
|
# /config here is the developer's bind-mounted checkout, not a data volume, so
|
|
# the prepare ownership sweep must not run: it would chown the source tree to
|
|
# the runtime uid and lock out any container user that isn't 1000.
|
|
ENV FRIGATE_RUN_AS_ROOT=true
|
|
|
|
# Do not start the actual Frigate service on devcontainer as it will be started by VS Code
|
|
# But start a fake service for simulating the logs
|
|
COPY docker/main/fake_frigate_run /etc/s6-overlay/s6-rc.d/frigate/run
|
|
|
|
# Create symbolic link to the frigate source code, as go2rtc's create_config.sh uses it
|
|
RUN mkdir -p /opt/frigate \
|
|
&& ln -svf /workspace/frigate/frigate /opt/frigate/frigate
|
|
|
|
# Install Node 20
|
|
RUN curl -SLO https://deb.nodesource.com/nsolid_setup_deb.sh && \
|
|
chmod 500 nsolid_setup_deb.sh && \
|
|
./nsolid_setup_deb.sh 20 && \
|
|
apt-get install nodejs -y \
|
|
&& rm -rf /var/lib/apt/lists/* \
|
|
&& npm install -g npm@10
|
|
|
|
WORKDIR /workspace/frigate
|
|
|
|
RUN apt-get update \
|
|
&& apt-get install make -y \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN --mount=type=bind,source=./docker/main/requirements-dev.txt,target=/workspace/frigate/requirements-dev.txt \
|
|
pip3 install -r requirements-dev.txt
|
|
|
|
HEALTHCHECK NONE
|
|
|
|
CMD ["sleep", "infinity"]
|
|
|
|
|
|
# Frigate web build
|
|
# This should be architecture agnostic, so speed up the build on multiarch by not using QEMU.
|
|
FROM --platform=$BUILDPLATFORM node:20 AS web-build
|
|
|
|
WORKDIR /work
|
|
COPY web/package.json web/package-lock.json ./
|
|
RUN npm install
|
|
|
|
COPY web/ ./
|
|
RUN npm run build \
|
|
&& mv dist/BASE_PATH/monacoeditorwork/* dist/assets/ \
|
|
&& rm -rf dist/BASE_PATH
|
|
|
|
# Collect final files in a single layer
|
|
FROM scratch AS rootfs
|
|
|
|
WORKDIR /opt/frigate/
|
|
COPY frigate frigate/
|
|
COPY migrations migrations/
|
|
COPY --from=web-build /work/dist/ web/
|
|
|
|
# Frigate final container
|
|
FROM deps AS frigate
|
|
|
|
WORKDIR /opt/frigate/
|
|
COPY --from=rootfs / /
|
|
ENV FRIGATE_IMAGE_VARIANT=standard
|
|
|
|
# Pre-compile bytecode so a read-only rootfs doesn't force re-parsing the
|
|
# source tree on every boot (pip-installed packages are already compiled)
|
|
RUN python3 -m compileall -q -j0 /opt/frigate/frigate
|