第 6 章:Dockerfile 与镜像构建
6.1 Dockerfile 是什么Dockerfile 是一个文本文件里面按顺序写着一系列指令。Docker 引擎读取这些指令逐行执行最终生成一个镜像。镜像与 Dockerfile 的关系1Dockerfile配方 2 ↓ docker build 3 镜像模板 4 ↓ docker run 5 容器运行实例什么时候需要写 Dockerfile把自己的代码打包成镜像需要安装额外的系统依赖如ffmpeg、gcc、libssl-dev需要定制化的启动命令或环境变量需要优化镜像体积、提升构建速度需要多阶段构建把编译产物提取到轻量运行镜像中6.2 Dockerfile 常用指令详解6.2.1FROM— 指定基础镜像dockerfile1FROM python:3.12-slim 2# 基于 Python 3.12 slim 版本构建 3 4FROM node:20-alpine 5# 基于 Node.js 20 Alpine 版本构建 6 7FROM nginx:1.27 8# 基于 Nginx 1.27 构建说明FROM必须是 Dockerfile 的第一条指令ARG除外。基础镜像决定了后续可用的系统环境和工具。基础镜像选择建议类型特点适用场景debian/ubuntu体积较大工具齐全需要系统级依赖的复杂应用slim精简版 Debian体积适中Python / Java 等应用的常规选择alpine极小体积基于 musl libc对体积敏感的服务注意兼容性问题distroless极小无 shell生产环境高安全要求场景6.2.2WORKDIR— 设置工作目录dockerfile1WORKDIR /app 2# 后续 RUN、COPY、CMD 等指令都在 /app 目录下执行 3 4COPY . . 5# 将文件复制到 /app 目录下建议始终使用WORKDIR而不是RUN cd /app ...。WORKDIR会在镜像中创建目录并切换语义更清晰。6.2.3COPYvsADD— 文件复制dockerfile1COPY requirements.txt /app/ 2# 将宿主机的 requirements.txt 复制到镜像的 /app/ 目录 3 4COPY . /app/ 5# 将当前构建上下文的所有文件复制到镜像中 6 7ADD https://example.com/app.tar.gz /app/ 8# ADD 支持自动解压 tar 文件和下载 URL不推荐用于 URL区别与选择指令功能推荐程度COPY复制本地文件优先使用ADD复制 自动解压 tar 下载 URL️ 仅在需要解压 tar 时使用建议除非需要自动解压.tar.gz文件否则一律使用COPY。ADD的隐式行为容易造成混淆。6.2.4RUN— 构建时执行命令dockerfile1RUN apt-get update apt-get install -y \ 2 gcc \ 3 libpq-dev \ 4 rm -rf /var/lib/apt/lists/* 5# 安装系统依赖安装后清理缓存以减小镜像体积 6 7RUN pip install --no-cache-dir -r requirements.txt 8# 安装 Python 依赖--no-cache-dir 避免缓存占用空间 9 10RUN npm install --production 11# 安装 Node.js 生产依赖建议多个相关命令用合并到一条RUN中减少镜像层数。每条RUN都会生成一个新层。6.2.5CMDvsENTRYPOINT— 启动命令重点这是 Dockerfile 中最容易混淆的两个指令。CMD— 提供默认启动命令可被docker run覆盖dockerfile1CMD [python, app.py] 2# 默认执行 python app.py1docker run myapp 2# 执行 python app.py 3 4docker run myapp bash 5# 覆盖为 bashCMD 被忽略ENTRYPOINT— 固定启动命令docker run的参数作为附加参数dockerfile1ENTRYPOINT [python, app.py] 2# 固定执行 python app.py1docker run myapp 2# 执行 python app.py 3 4docker run myapp --port 8080 5# 执行 python app.py --port 8080两者配合使用最佳实践dockerfile1ENTRYPOINT [python, app.py] 2CMD [--port, 5000] 3# ENTRYPOINT 固定命令CMD 提供默认参数1docker run myapp 2# 执行 python app.py --port 5000 3 4docker run myapp --port 8080 5# 执行 python app.py --port 8080JSON 数组格式 vs Shell 格式dockerfile1# JSON 数组格式推荐— 不会经过 shell 解析 2CMD [python, app.py] 3 4# Shell 格式 — 实际执行 /bin/sh -c python app.py 5CMD python app.py建议优先使用 JSON 数组格式。Shell 格式无法正确接收信号如docker stop的 SIGTERM可能导致容器无法优雅停止。6.2.6ENV— 设置环境变量dockerfile1ENV APP_ENVproduction 2ENV PORT8080 3 4# 在后续指令中引用 5RUN echo $APP_ENV 6CMD [python, app.py]bash1docker run -e APP_ENVstaging myapp 2# 运行时覆盖环境变量场景数据库连接串、API 密钥、日志级别等配置通过环境变量注入方便同一镜像在不同环境开发/测试/生产中使用。6.2.7EXPOSE— 声明端口dockerfile1EXPOSE 8080 2# 声明容器运行时监听 8080 端口说明EXPOSE只是文档性质的声明不会自动映射端口。实际端口映射仍需在docker run时使用-p参数。6.2.8ARG— 构建参数dockerfile1ARG APP_VERSION1.0 2ARG BUILD_ENVproduction 3 4RUN echo Building version $APP_VERSION for $BUILD_ENVbash1docker build --build-arg APP_VERSION2.0 --build-arg BUILD_ENVstaging -t myapp . 2# 构建时传入参数说明ARG仅在构建时有效运行时不存在。ENV在构建时和运行时都有效。6.2.9LABEL— 镜像元信息dockerfile1LABEL maintainerdevexample.com 2LABEL version1.0 3LABEL descriptionMy Flask Application说明用于标记镜像的作者、版本、描述等信息方便团队协作和镜像管理。6.2.10USER— 切换用户dockerfile1RUN useradd -m appuser 2USER appuser 3# 后续指令及容器运行时都以 appuser 身份执行建议生产环境不要以root运行容器。使用USER切换到非特权用户提升安全性。6.2.11HEALTHCHECK— 健康检查dockerfile1HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ 2 CMD curl -f http://localhost:8080/health || exit 1参数说明参数含义--interval检查间隔--timeout超时时间--start-period启动宽限期容器启动后多久开始检查--retries连续失败多少次判定为不健康bash1docker ps 2# 健康状态会显示在 STATUS 列中healthy / unhealthy场景配合 Kubernetes、Docker Swarm 等编排工具自动重启不健康的容器。6.3 构建镜像docker build6.3.1 基本构建命令bash1docker build -t myapp:1.0 . 2# -t给镜像打标签 3# .使用当前目录作为构建上下文6.3.2 指定 Dockerfile 路径bash1docker build -t myapp:1.0 -f Dockerfile.prod . 2# -f指定 Dockerfile 文件名6.3.3 禁用缓存bash1docker build --no-cache -t myapp:1.0 . 2# 每次构建都重新执行所有指令不使用缓存场景当构建缓存导致旧代码或旧依赖被使用时用--no-cache强制重新构建。6.3.4 传入构建参数bash1docker build --build-arg APP_VERSION2.0 -t myapp:2.0 . 2# 传入 ARG 参数6.3.5.dockerignore文件在项目根目录创建.dockerignore排除不需要复制到镜像中的文件1.git 2node_modules 3__pycache__ 4*.pyc 5.env 6Dockerfile 7docker-compose.yml 8README.md说明.dockerignore的作用类似.gitignore可以减少构建上下文大小加快构建速度同时避免敏感文件如.env被打包进镜像。6.4 构建缓存与层优化Docker 构建时会缓存每一层的结果。如果某一层及其之前的所有层都没有变化Docker 会直接使用缓存跳过执行。指令顺序对构建速度的影响dockerfile1# 不好的顺序 — 代码变化会导致 pip install 重新执行 2COPY . /app/ 3RUN pip install -r requirements.txt 4 5# 好的顺序 — 依赖文件不变时pip install 使用缓存 6COPY requirements.txt /app/ 7RUN pip install -r requirements.txt 8COPY . /app/原理requirements.txt变化频率远低于代码文件。先复制依赖文件并安装再复制代码可以充分利用缓存大幅提升构建速度。Node.js 项目同理dockerfile1COPY package.json package-lock.json /app/ 2RUN npm install 3COPY . /app/6.5 镜像体积优化实战6.5.1 选择轻量基础镜像dockerfile1# 体积约 1GB 2FROM python:3.12 3 4# 体积约 150MB 5FROM python:3.12-slim 6 7# 体积约 50MB 8FROM python:3.12-alpine注意Alpine 基于 musl libc某些 Python 包如numpy、pandas可能需要额外编译构建时间可能更长。根据项目实际情况选择。6.5.2 多阶段构建Multi-stage Build这是镜像体积优化的最重要手段。Go 应用示例dockerfile1# 第一阶段编译 2FROM golang:1.22 AS builder 3 4WORKDIR /app 5COPY go.mod go.sum ./ 6RUN go mod download 7COPY . . 8RUN CGO_ENABLED0 GOOSlinux go build -o myapp . 9 10# 第二阶段运行 11FROM alpine:3.19 12 13WORKDIR /app 14COPY --frombuilder /app/myapp . 15EXPOSE 8080 16CMD [./myapp]说明最终镜像只包含编译后的二进制文件不包含 Go 编译器和源码体积从 ~800MB 降到 ~15MB。Python 应用示例dockerfile1# 第一阶段安装依赖 2FROM python:3.12-slim AS builder 3 4WORKDIR /app 5COPY requirements.txt . 6RUN pip install --no-cache-dir --prefix/install -r requirements.txt 7 8# 第二阶段运行 9FROM python:3.12-slim 10 11WORKDIR /app 12COPY --frombuilder /install /usr/local 13COPY . . 14EXPOSE 5000 15CMD [python, app.py]Node.js 应用示例dockerfile1# 第一阶段构建 2FROM node:20-alpine AS builder 3 4WORKDIR /app 5COPY package.json package-lock.json ./ 6RUN npm ci 7COPY . . 8RUN npm run build 9 10# 第二阶段运行 11FROM node:20-alpine 12 13WORKDIR /app 14COPY --frombuilder /app/dist ./dist 15COPY --frombuilder /app/node_modules ./node_modules 16COPY package.json ./ 17EXPOSE 3000 18CMD [node, dist/index.js]6.5.3 合并 RUN 指令dockerfile1# 生成多个层 2RUN apt-get update 3RUN apt-get install -y gcc 4RUN apt-get install -y libpq-dev 5RUN rm -rf /var/lib/apt/lists/* 6 7# 合并为一条减少层数 8RUN apt-get update apt-get install -y \ 9 gcc \ 10 libpq-dev \ 11 rm -rf /var/lib/apt/lists/*6.5.4 清理构建缓存dockerfile1# Python 2RUN pip install --no-cache-dir -r requirements.txt 3 4# Debian/Ubuntu 5RUN apt-get update apt-get install -y xxx \ 6 rm -rf /var/lib/apt/lists/* 7 8# Alpine 9RUN apk add --no-cache xxx6.6 多项目类型实战6.6.1 Python Flask 应用项目结构1flask-app/ 2├── app.py 3├── requirements.txt 4├── .dockerignore 5└── Dockerfilerequirements.txt1flask3.0.0 2gunicorn21.2.0Dockerfile1FROM python:3.12-slim 2 3WORKDIR /app 4 5# 先复制依赖文件利用缓存 6COPY requirements.txt . 7RUN pip install --no-cache-dir -r requirements.txt 8 9# 再复制代码 10COPY . . 11 12# 非 root 用户运行 13RUN useradd -m appuser 14USER appuser 15 16EXPOSE 5000 17 18# 使用 gunicorn 作为生产 WSGI 服务器 19CMD [gunicorn, --bind, 0.0.0.0:5000, app:app]构建与运行1docker build -t flask-app:1.0 . 2# 构建镜像 3 4docker run -d \ 5 --name flask-app \ 6 -p 5000:5000 \ 7 flask-app:1.0 8# 运行容器说明生产环境使用gunicorn而非 Flask 内置服务器。gunicorn支持多 worker、优雅重启性能更好。6.6.2 Node.js Express 应用项目结构1node-app/ 2├── src/ 3│ └── index.js 4├── package.json 5├── package-lock.json 6├── .dockerignore 7└── DockerfileDockerfile1FROM node:20-alpine 2 3WORKDIR /app 4 5# 先复制依赖文件 6COPY package.json package-lock.json ./ 7RUN npm ci --onlyproduction 8 9# 再复制代码 10COPY src/ ./src/ 11 12# 非 root 用户 13RUN addgroup -S appgroup adduser -S appuser -G appgroup 14USER appuser 15 16EXPOSE 3000 17 18CMD [node, src/index.js]说明npm ci比npm install更快、更确定它严格按照package-lock.json安装依赖适合 CI/CD 和 Docker 构建。--onlyproduction跳过devDependencies减小体积。6.6.3 Go Web 应用项目结构1go-app/ 2├── main.go 3├── go.mod 4├── go.sum 5└── DockerfileDockerfile多阶段构建1# 编译阶段 2FROM golang:1.22-alpine AS builder 3 4WORKDIR /app 5COPY go.mod go.sum ./ 6RUN go mod download 7COPY . . 8RUN CGO_ENABLED0 GOOSlinux go build -ldflags-s -w -o myapp . 9 10# 运行阶段 11FROM alpine:3.19 12 13WORKDIR /app 14COPY --frombuilder /app/myapp . 15 16EXPOSE 8080 17CMD [./myapp]说明-ldflags-s -w去掉调试信息进一步减小二进制体积。Go 编译后是静态二进制文件运行阶段甚至可以使用scratch空镜像。6.6.4 Nginx 静态站点项目结构1static-site/ 2├── dist/ 3│ ├── index.html 4│ ├── css/ 5│ └── js/ 6├── nginx.conf 7└── Dockerfilenginx.conf1server { 2 listen 80; 3 server_name localhost; 4 root /usr/share/nginx/html; 5 index index.html; 6 7 location / { 8 try_files $uri $uri/ /index.html; 9 } 10}Dockerfile1FROM nginx:1.27-alpine 2 3# 复制自定义配置 4COPY nginx.conf /etc/nginx/conf.d/default.conf 5 6# 复制静态文件 7COPY dist/ /usr/share/nginx/html/ 8 9EXPOSE 80构建与运行1docker build -t my-site:1.0 . 2docker run -d --name my-site -p 80:80 my-site:1.0场景Vue / React / Angular 等前端项目构建后生成dist目录用 Nginx 托管是最常见的部署方式。try_files配置确保 SPA 路由刷新时不会 404。6.6.5 Java Spring Boot 应用项目结构1java-app/ 2├── src/ 3├── pom.xml 4├── target/ 5│ └── myapp.jar 6└── DockerfileDockerfile多阶段构建1# 编译阶段 2FROM maven:3.9-eclipse-temurin-17 AS builder 3 4WORKDIR /app 5COPY pom.xml . 6COPY src ./src 7RUN mvn clean package -DskipTests 8 9# 运行阶段 10FROM eclipse-temurin:17-jre-alpine 11 12WORKDIR /app 13COPY --frombuilder /app/target/myapp.jar . 14 15EXPOSE 8080 16CMD [java, -jar, myapp.jar]说明运行阶段使用 JRE 而非 JDK体积更小。-DskipTests跳过测试加快构建CI 环境中测试应在构建前单独执行。6.7 镜像推送与私有仓库6.7.1 登录 Docker Hub1docker login 2# 输入 Docker Hub 用户名和密码6.7.2 重新打标签1docker tag myapp:1.0 username/myapp:1.0 2# username 是你的 Docker Hub 用户名6.7.3 推送镜像1docker push username/myapp:1.0 2# 推送到 Docker Hub6.7.4 拉取镜像1docker pull username/myapp:1.0 2# 从 Docker Hub 拉取6.7.5 私有仓库简介仓库类型说明Docker Hub公共仓库免费私有仓库需付费阿里云 ACR国内访问速度快有免费个人版Harbor开源私有仓库可自建GitHub Container Registry与 GitHub 深度集成建议国内团队优先使用阿里云 ACR 或自建 Harbor避免 Docker Hub 拉取速度慢的问题。6.8 常见错误排查问题原因解决方案COPY failed: file not found文件不在构建上下文中检查.dockerignore和文件路径容器启动后立即退出CMD/ENTRYPOINT 命令执行完毕或报错用docker logs查看错误信息端口无法访问未使用-p映射端口docker run -p 宿主机端口:容器端口docker run覆盖了 CMDCMD 可被覆盖需要固定命令时使用 ENTRYPOINT构建缓存未更新Docker 使用了旧缓存使用--no-cache或调整指令顺序

相关新闻

Multi\-Model Quickstart:用一套OpenAI SDK调用多个模型

Multi\-Model Quickstart:用一套OpenAI SDK调用多个模型

一个AI项目接入第二个模型供应商之后,真正的问题才暴露出来。代码没有变得更难写,而是变得更难改。供应商A的流式返回格式和供应商B不同,工具调用的参数结构对不上,错误码体系各自为政。每新增一个模型,业务代码里就多…

2026/10/11 7:31:51 阅读更多 →
[Linux操作系统] 添加、修改与删除用户和用户组

[Linux操作系统] 添加、修改与删除用户和用户组

用户名称:jiwang 用户密码:x UID:1000 GID:1000 用户说明信息:jiwang: 用户家(主)目录:bin 用户的Shell:bin/bash创建一个普通用户lkr创建普通用户ls,用户UID为1111,GID为…

2026/10/11 7:31:51 阅读更多 →
冰封末日生存沙盒:4K画质优化与全流程通关攻略

冰封末日生存沙盒:4K画质优化与全流程通关攻略

开头部分如果写太长,注意控制在合理范围。我直接开始。在冰封末日题材的生存沙盒游戏里,最劝退玩家的往往不是暴风雪本身,而是两个问题叠在一起:前期反复冻死饿死,不知道该优先干什么;后期好不容易把画质拉…

2026/10/11 7:30:51 阅读更多 →

最新新闻

从代码规范到质量门禁:用impeccable标准打造可落地的工程检查体系

从代码规范到质量门禁:用impeccable标准打造可落地的工程检查体系

1. 一个词撑起一个项目:为什么“impeccable”值得单独拿出来做第一次看到有人拿“impeccable”当项目名,我脑子里蹦出来的不是词典释义,而是一个很具体的场景:代码评审时,有人提了一句“这个模块的边界处理不够 impecc…

2026/10/11 9:57:55 阅读更多 →
DeepSeek-R1本地部署实战:RTX 3060跑32B量化模型全链路指南

DeepSeek-R1本地部署实战:RTX 3060跑32B量化模型全链路指南

简介:本资源是一份面向开发者与AI技术爱好者的DeepSeek大模型本地化实践指南,聚焦低门槛部署、跨设备适配与生产级性能优化。内容覆盖从硬件选型(7B至32B模型在GTX 1060/RTX 4090等消费级显卡的实测配置)、Ollama极简部署&#xf…

2026/10/11 9:57:55 阅读更多 →
测试面试复盘:5年经验为何败给底层原理

测试面试复盘:5年经验为何败给底层原理

先说结论:5年测试经验,不代表面试能答得上技术问题。被裁后重新求职,我自以为手握几年项目经历,多少有点底气,结果第一次技术面就差点被问得当场红眼眶。不是面试官故意为难,而是那些问题全部戳在“我每天在…

2026/10/11 9:57:55 阅读更多 →
IEEE 802.16e移动WiMAX中LDPC编译码实现与标准合规验证

IEEE 802.16e移动WiMAX中LDPC编译码实现与标准合规验证

简介:本资源是一份面向通信工程专业高年级本科生及FPGA开发工程师的LDPC编码实践资料,聚焦IEEE 802.16e标准中LDPC码的硬件高效实现问题,解决传统编码方案预处理复杂、逻辑资源消耗大、实时性不足等关键瓶颈。资料以1个446KB的PDF文件呈现&am…

2026/10/11 9:57:55 阅读更多 →
Python汽车销售数据分析大屏:Pandas清洗+Flask+ECharts可视化系统

Python汽车销售数据分析大屏:Pandas清洗+Flask+ECharts可视化系统

简介:这是一套面向计算机及相关专业学生的Python汽车数据分析大屏可视化实战项目,专为期末大作业、课程设计及毕业设计场景打造,兼顾教学规范性与工程可运行性。资源包含完整可执行源码、详细文档说明及多阶段过程材料,经导师指导…

2026/10/11 9:57:55 阅读更多 →
Apache Beam Calcite SQL 标量函数完全指南:从比较运算到日期/字符串处理的完整参考

Apache Beam Calcite SQL 标量函数完全指南:从比较运算到日期/字符串处理的完整参考

【免费下载链接】beam Apache Beam is a unified programming model for Batch and Streaming data processing. 项目地址: https://gitcode.com/gh_mirrors/beam18/beam 点击查看 免费下载 Apache Beam 的 Calcite SQL 方言(Beam Calcite SQL&#xff…

2026/10/11 9:56:54 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →