如何把 TeslaMate 的 Docker 镜像做小:构建上下文、多阶段与运行时精简

发布时间:2026/9/19 2:43:53
如何把 TeslaMate 的 Docker 镜像做小:构建上下文、多阶段与运行时精简 如何把 TeslaMate 的 Docker 镜像做小构建上下文、多阶段与运行时精简【免费下载链接】teslamateA self-hosted data logger for your Tesla [main maintainerJakobLichterfeld]项目地址: https://gitcode.com/GitHub_Trending/te/teslamateTeslaMate 是一个自托管的特斯拉数据记录器持续从车辆采集位置、能耗、充电等数据写入 Postgres并用 Grafana 可视化。用 Docker 部署它时常见的问题是镜像层数多、体积大慢网络下拉取一次要等很久自建服务器磁盘也吃不消。下面从构建上下文瘦身、两阶段构建、运行时依赖裁剪三个方向入手目标是让传输量和最终镜像都只保留运行必需的部分。先把基线数据摸清楚动手之前先用两条命令确认现状后面所有优化都靠这组数字对比。docker history teslamate/teslamate:latest docker image ls teslamate/teslamatehistory输出按层展开镜像构成能看到每一层是什么、占多少体积image ls给出最终大小。把结果记下来作为基线。另外在源码目录里跑一下du -sh --exclude.git .和du -sh */能直接看到构建上下文的构成——本仓库VERSION 为 4.3.0-dev源码树约 40MB其中website/文档站目录独占 31MBtest/占 5.4MB而真正会被COPY进镜像的lib/、config/、priv/加起来不到 3MB。按收益排序先砍构建上下文收益最大、成本最低的一步是让 Docker 少传文件。构建时整个上下文目录都会发送到 daemon即使 Dockerfile 从不COPY它。仓库现有的 .dockerignore 已排除test/、node_modules、_build/把website/也加进去后上传量从约 35MB 降到约 4MB接近九成减少且对镜像内容零影响——文档站由独立流水线发布与运行镜像无关。两阶段构建把编译工具链挡在最终镜像外官方 Dockerfile 已经是两阶段结构自建镜像时务必保留这个模式而不是图省事用单层构建。第一阶段基于elixir:1.20.2-otp-29再装 Node 22跑mix deps.get --only prod、npm ci、mix assets.deploy、mix compile最后mix release --path /opt/built。第二阶段基于debian:trixie-slim只执行一条COPY --frombuilder /opt/built .。关键点在于第二阶段的COPY只取/opt/built这个 release 产物目录Elixir 编译器、Hex 缓存、_build/编译中间态、Node 工具链全部留在 builder 层不进入最终镜像。单层构建则会把这套几百 MB 的工具链全部带进最终层拉取时间和磁盘占用成倍上升。运行时依赖裁剪到最少最终阶段的apt-get install用了--no-install-recommends只装了 6 个包libodbc2、libsctp1、libssl3t64、libstdc6、netcat-openbsd、tini外加tzdata。其中 netcat 是 entrypoint.sh 等待 Postgres 就绪用的tini 负责信号转发删任何一个都会破坏启动流程。装完立即apt-get clean rm -rf /var/lib/apt/lists/*避免缓存留在层里。自建镜像时不要加回构建工具git、vim、curl 全家桶排障可以docker exec进临时容器解决。COPY 顺序决定缓存命中率Dockerfile 里的复制顺序是刻意安排的先mix.exs、mix.lock再deps.get然后config/再deps.compile接着assets/、priv/static做前端资源最后才复制lib/和priv/业务代码做mix compile。只改业务代码时依赖层和资产层全部命中缓存重建只有最后几分钟。把顺序打乱比如先复制全部源码再装依赖每次提交都会触发依赖重装构建时间从分钟级回到十分钟级。拉取侧同理Makefile 里的make teslamate带--pull拉取基础镜像配合 CI 的 buildx 缓存能让日常构建只传变化的层。一个容易踩的坑grafana/dashboards 不能删有人看到 grafana/dashboards/ 下 20 多个 JSON 文件约 864KB觉得是冗余想剔除。不能。Web 界面的仪表盘下拉菜单由 lib/teslamate_web/views/layout_view.ex 在编译时Path.wildcard(grafana/dashboards/*.json)生成删掉它 web 端菜单直接空掉。这 864KB 是功能的一部分保留。前后对比以 40MB 源码树为基线指标优化前优化后构建上下文上传量约 35MB含 31MB 的 website/约 4MB最终镜像中的编译工具链整段 builderElixir Node Hex 缓存仅/opt/builtrelease 目录最终镜像 apt 包带 recommends 的完整集合6 个运行时库依赖层缓存每次提交全量重装仅业务代码变更时重编验证构建结果重新构建后复查两件事docker history确认最终阶段只有 slim 基础层加 release 层没有混入 builder 层容器启动后 entrypoint.sh 会先轮询 Postgres 端口、自动执行迁移、再拉起bin/teslamate start访问 4000 端口能看到登录页即说明裁剪没有破坏运行时。长期维护只保留两条每次发布用docker build --pullMakefile 已内置更新基础镜像并盯住 CI 产出的镜像体积曲线出现跳变说明有人往上下文或运行时层里加了东西。Grafana 镜像由独立的 grafana/Dockerfile 构建部署方案见 website/docs/installation/docker.md不要把 Grafana 的仪表盘 JSON 之外的东西塞回主镜像两个镜像各管各的体积。【免费下载链接】teslamateA self-hosted data logger for your Tesla [main maintainerJakobLichterfeld]项目地址: https://gitcode.com/GitHub_Trending/te/teslamate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考