Files
HomeDash/Dockerfile
JianFeeeee 12c07034a0 fix(cert): cert-agent 真实签发验证后修的三处问题
在测试容器里用真实凭据跑通了完整签发(staging CA),暴露三个真问题:

## ① CERT_DNS_CRED 没导出成 acme.sh 期望的变量名(致命)
脚本只把凭据解析出插件名 dns_ali,却从没导出 Ali_Key/Ali_Secret。
acme.sh 的 dns_ali.sh 读的是 $Ali_Key/$Ali_Secret,所以 DNS 步骤
报 'Error adding TXT record',而 ACME 其它步骤全部正常 ——
极易误判成"凭据无效/网络问题"。**stub 测试完全没暴露这个**,
只有真跑才看得见。现改为把 CERT_DNS_CRED 按逗号拆开逐个 export。

## ② 镜像内置 acme.sh,不再运行时下载
installer 内部从 raw.githubusercontent.com 取源码,而该域名境内直连超时
(实测直连 8.2s 失败 / 经 .60:7890 代理 0.53s 成功),
首次启动会静默失败、之后永远起不来。Dockerfile 新增 acmebuild stage
内置 acme.sh v3.1.6,运行时安装降级为兜底。

## ③ 下载重试 + 安装后校验
容器出网偶发 Connection reset by peer(同一 URL 隔几秒即 200),
加了 3 次重试与「安装后确认可执行」,避免半截状态。

## 真实测试证据(staging CA,零正式配额消耗)
TXT 写入 → Verifying → Success → Successfully removed → Cert success;
签出 CN=dashy.jianfgit.xyz(Let's Encrypt YE1,90 天);
Le_ReloadCmd 已写入 ⇒ 续期后自动 nginx -t && nginx -s reload。

测试环境已清理(含凭据文件),线上 v106 未受影响。
2026-10-04 08:29:35 +08:00

140 lines
6.1 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 不用 `# syntax=docker/dockerfile:1`:该指令会让 BuildKit 去 pull
# docker/dockerfile 前端镜像,在无外网/仅代理的环境里会直接构建失败。
# 本文件未使用任何 BuildKit 专有语法,去掉后走内置前端即可。
# ── Stage 1: Go binaries ──
FROM golang:1.21-bookworm AS gobuild
WORKDIR /src/history
COPY history-server/ .
RUN GOPROXY=https://goproxy.cn,direct CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/history-server .
WORKDIR /src/admin
COPY admin-server/ .
RUN GOPROXY=https://goproxy.cn,direct go mod tidy && CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/admin-server .
# ── Stage 2: SearXNG from source ──
FROM debian:bookworm-slim AS searxng-build
# 需要代理时用 --build-arg 传入(默认不设,保证他人环境可直接构建)
ARG HTTP_PROXY=
ARG HTTPS_PROXY=
ENV DEBIAN_FRONTEND=noninteractive
ENV http_proxy=${HTTP_PROXY}
ENV https_proxy=${HTTPS_PROXY}
ENV HTTP_PROXY=${HTTP_PROXY}
ENV HTTPS_PROXY=${HTTPS_PROXY}
RUN apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
python3 python3-pip python3-venv git ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN git clone --depth 1 https://github.com/searxng/searxng.git /src/searxng \
&& python3 -m venv /opt/searxng-venv \
&& /opt/searxng-venv/bin/pip install --upgrade pip setuptools wheel msgspec \
&& cd /src/searxng \
&& /opt/searxng-venv/bin/pip install --no-cache-dir -r requirements.txt \
&& /opt/searxng-venv/bin/pip install --no-cache-dir --no-build-isolation . \
&& rm -rf /src/searxng
# ── Stage 3: browser extension packages ──
# 供 /extension/install.html 下载(Chromium 用 zip,Firefox 用 xpi)
FROM debian:bookworm-slim AS extpack
RUN apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends zip ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY extension/chrome /src/chrome
COPY extension/firefox /src/firefox
# Go 的 -o 会自动建父目录,zip 不会,所以这里必须显式创建 /out
RUN mkdir -p /out \
&& cd /src/chrome && zip -qr /out/navi-chrome.zip . \
&& cd /src/firefox && zip -qr /out/navi-firefox.xpi .
# ── Stage 3b: bundled acme.sh (for cert-agent) ──
# 为什么要内置:cert-agent 若在运行时安装 acme.sh,installer 会从
# raw.githubusercontent.com 拉源码,而该域名在境内直连超时
# (实测直连 8.2s 失败 / 经代理 0.53s 成功),导致首次启动静默失败。
# 内置一份让 cert-agent 彻底不依赖运行时下载。
FROM debian:bookworm-slim AS acmebuild
RUN apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
git ca-certificates curl openssl \
&& rm -rf /var/lib/apt/lists/*
RUN git clone --depth 1 https://github.com/acmesh-official/acme.sh /src/acme.sh \
&& chmod +x /src/acme.sh/acme.sh \
&& rm -rf /src/acme.sh/.git
# ── Stage 4: Runtime ──
FROM debian:bookworm-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
nginx python3 supervisor curl ca-certificates git \
&& rm -rf /var/lib/apt/lists/*
# Copy SearXNG venv + source
COPY --from=searxng-build /opt/searxng-venv /app/searxng-venv
COPY --from=searxng-build /usr/lib/python3.11 /usr/lib/python3.11
COPY --from=searxng-build /lib/x86_64-linux-gnu /lib/x86_64-linux-gnu
COPY --from=searxng-build /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu
# Dashy static files
COPY --from=lissy93/dashy:latest /app/dist /app/dashy
# Go binaries
COPY --from=gobuild /out/history-server /usr/local/bin/history-server
COPY --from=gobuild /out/admin-server /usr/local/bin/admin-server
# Config files
COPY nginx.conf /etc/nginx/nginx.conf
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY searxng-settings.yml /etc/searxng/settings.yml
COPY conf.example.yml /app/defaults/conf.yml
COPY admin/index.html /app/admin/index.html
COPY portal /app/portal
# 站点图标:纸飞机。覆盖 Dashy 自带的 web-icons/favicon-*.png,
# 这样即使将来上游 index.html 变了、patch 失效,标签栏仍是我们的图标。
COPY portal/favicon.svg /app/dashy/favicon.svg
COPY portal/favicon.ico /app/dashy/favicon.ico
COPY portal/apple-touch-icon.png /app/dashy/apple-touch-icon.png
COPY portal/web-icons/ /app/dashy/web-icons/
# 见 zd-host.sh 同名注释:Dashy 前端 JS 运行时会把 icon link 改成
# /icons/favicon.ico,而镜像里没有 /icons/ 目录,静态改 index.html 无效。
COPY portal/favicon.ico /app/dashy/icons/favicon.ico
COPY portal/favicon.svg /app/dashy/icons/favicon.svg
# 浏览器扩展安装页与安装包(通过 /extension/ 访问)
COPY web/extension/install.html /app/dashy/extension/install.html
COPY --from=extpack /out/navi-chrome.zip /app/dashy/extension/navi-chrome.zip
COPY --from=extpack /out/navi-firefox.xpi /app/dashy/extension/navi-firefox.xpi
# 容器内自动续签(cert-agent)。脚本本身不含任何凭据,凭据只从环境变量读。
COPY deploy/cert-agent.sh /usr/local/bin/cert-agent
RUN chmod +x /usr/local/bin/cert-agent
# 内置 acme.sh:cert-agent 优先用它,避免运行时从 raw.githubusercontent.com
# 下载失败(该域名境内直连超时)。
COPY --from=acmebuild /src/acme.sh /usr/local/share/acme.sh
# Inject search script into Dashy
COPY web/navi.js /app/dashy/navi.js
COPY web/navi.css /app/dashy/navi.css
COPY web/patch-index.py /tmp/patch-index.py
# index.html 里不一定有 </body>,用脚本幂等注入,不能靠 sed 替换 </body>。
RUN python3 /tmp/patch-index.py /app/dashy/index.html
# Data directory
RUN mkdir -p /app/data/item-icons /app/data/gateway /app/data/certs /app/data/acme /var/log/supervisor /var/cache/searxng /run/nginx
VOLUME ["/app/data"]
EXPOSE 18080 3080 3081 8443
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD curl -fs http://localhost:18080/healthz || exit 1
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]