# syntax=docker/dockerfile:1.7 # 默认通过已验证的国内代理读取 FFmpeg;导出脚本还会按相同摘要自动选择备用代理。 ARG FFMPEG_IMAGE=docker.1ms.run/mwader/static-ffmpeg:6.1 # 构建阶段使用完整的 Maven + JDK 8,最终镜像不会保留 Maven 和源码。 FROM --platform=$BUILDPLATFORM maven:3.9.9-eclipse-temurin-8 AS builder ARG MAVEN_MIRROR_URL=https://maven.aliyun.com/repository/public ENV MAVEN_MIRROR_URL=${MAVEN_MIRROR_URL} WORKDIR /workspace # Maven 镜像地址通过构建参数注入,国内默认使用阿里云,也可切回 Maven Central。 COPY deploy/docker/maven-settings.xml /tmp/maven-settings.xml # 三个厂商 JAR 未发布到公共 Maven 仓库,先安装到镜像内的本地仓库。 # 这里使用普通构建层持久化仓库;若改用 BuildKit 缓存挂载,安装层命中缓存但 # 挂载内容已被回收时,后续 Maven 会错误地转向公共镜像查找这些私有依赖。 COPY lib/jna.jar lib/examples.jar lib/INetSDK.jar /tmp/vendor/ RUN mvn -s /tmp/maven-settings.xml -B -ntp install:install-file \ -Dfile=/tmp/vendor/jna.jar \ -DgroupId=net.java.jna \ -DartifactId=jna \ -Dversion=1.0.0 \ -Dpackaging=jar \ && mvn -s /tmp/maven-settings.xml -B -ntp install:install-file \ -Dfile=/tmp/vendor/examples.jar \ -DgroupId=net.java.examples \ -DartifactId=examples \ -Dversion=1.0.0 \ -Dpackaging=jar \ && mvn -s /tmp/maven-settings.xml -B -ntp install:install-file \ -Dfile=/tmp/vendor/INetSDK.jar \ -DgroupId=net.dahua.netsdk \ -DartifactId=dahua-netsdk-jni \ -Dversion=1.0.0 \ -Dpackaging=jar # 先下载依赖,使普通源码变更能够复用 Maven 依赖层。 COPY pom.xml ./ RUN mvn -s /tmp/maven-settings.xml -B -ntp -DskipTests \ -Dmaven.wagon.http.retryHandler.count=5 \ dependency:go-offline COPY src ./src RUN mvn -s /tmp/maven-settings.xml -B -ntp -DskipTests \ -Dmaven.wagon.http.retryHandler.count=5 \ clean package # 直接复用预编译的静态 FFmpeg,使视频处理与厂商 SDK 均在 x86_64 上原生运行。 FROM --platform=$TARGETPLATFORM ${FFMPEG_IMAGE} AS ffmpeg # 厂商 Linux64 SDK 依赖 glibc,因此运行阶段使用 Ubuntu 系 JRE 镜像。 FROM eclipse-temurin:8-jre-focal AS runtime ARG TARGETARCH ARG HIK_SDK_ROOT=lib/hik-linux64 ARG DAHUA_SDK_ROOT=lib/dahua-linux64 ARG UBUNTU_MIRROR=https://mirrors.aliyun.com/ubuntu # 两套厂商库均为 x86_64,构建时阻止误选其他平台导致 JNA 加载失败。 RUN test "${TARGETARCH}" = "amd64" \ || (echo "inspect-nvr 当前 Docker 镜像只支持 linux/amd64:lib 中的海康和大华 SDK 均为 x86_64。" >&2; exit 1) ENV DEBIAN_FRONTEND=noninteractive \ TZ=Asia/Shanghai # 将 Ubuntu 官方软件源替换为国内阿里云镜像,避免构建时因跨境链路超时或 502 中断。 RUN sed -i \ -e "s|http://archive.ubuntu.com/ubuntu|${UBUNTU_MIRROR}|g" \ -e "s|http://security.ubuntu.com/ubuntu|${UBUNTU_MIRROR}|g" \ /etc/apt/sources.list # 海康播放与渲染组件会动态加载 X11、OpenGL 和 EGL;即使无桌面环境也需保留这些运行库。 RUN apt-get -o Acquire::Retries=5 update \ && apt-get -o Acquire::Retries=5 install -y --no-install-recommends libx11-6 libgl1 libegl1 \ && rm -rf /var/lib/apt/lists/* # 语音对讲与视频输出组件还会按需加载 ALSA 和 XVideo,统一放入运行镜像避免功能触发时才报缺库。 RUN apt-get -o Acquire::Retries=5 update \ && apt-get -o Acquire::Retries=5 install -y --no-install-recommends libasound2 libxv1 \ && rm -rf /var/lib/apt/lists/* # 静态 FFmpeg 不依赖运行镜像中的共享库,适合跨架构构建和部署。 COPY --from=ffmpeg /ffmpeg /usr/bin/ffmpeg COPY --from=ffmpeg /ffprobe /usr/bin/ffprobe RUN groupadd --gid 10001 inspect-nvr \ && useradd --uid 10001 --gid inspect-nvr --home-dir /app --shell /usr/sbin/nologin inspect-nvr \ && mkdir -p /app/lib/HCNetSDKCom /app/lib/linux64 \ /app/images /app/sdkLog /app/sdklog /app/target /data/logs/inspect-nvr \ && chown -R inspect-nvr:inspect-nvr /app /data/logs WORKDIR /app COPY --from=builder --chown=inspect-nvr:inspect-nvr /workspace/target/inspect-nvr.jar ./app.jar # 直接从厂商 Linux64 开发包复制 x86_64 运行库,避免混入旧 ARM64 库或 Windows DLL。 COPY --chown=inspect-nvr:inspect-nvr ${HIK_SDK_ROOT}/ ./lib/ COPY --chown=inspect-nvr:inspect-nvr ${DAHUA_SDK_ROOT}/ ./lib/linux64/ COPY --chown=inspect-nvr:inspect-nvr \ lib/DemoLocalCfg.json \ lib/DeviceCfg.json \ lib/LocalSensorAdd.dat \ lib/license.dat \ ./lib/ # JNA 除了按绝对路径加载主库,还会从这些目录解析 SDK 的级联依赖。 ENV LD_LIBRARY_PATH=/app/lib:/app/lib/HCNetSDKCom:/app/lib/linux64 \ JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom -Djava.library.path=/app/lib:/app/lib/HCNetSDKCom:/app/lib/linux64" USER inspect-nvr EXPOSE 8081 HEALTHCHECK --interval=30s --timeout=5s --start-period=90s --retries=5 \ CMD curl --fail --silent --show-error http://127.0.0.1:8081/ > /dev/null || exit 1 ENTRYPOINT ["java", "-jar", "/app/app.jar"]