Docker 容器化部署最佳实践:从镜像优化到生产环境安全配置
容器化技术已经成为现代应用部署的标准方式,Docker 作为最流行的容器 runtime,其使用方式直接影响应用的性能、安全性和可维护性。本文将从生产环境实战角度,系统梳理 Docker 容器化部署的最佳实践,涵盖镜像构建优化、安全配置、资源管理、网络与存储等核心维度。
一、Dockerfile 镜像构建优化
镜像构建是容器化的第一步,优秀的 Dockerfile 不仅能减小镜像体积,还能提升构建速度和运行时安全性。
1.1 选择合适的基础镜像
基础镜像的选择直接决定了镜像的大小和攻击面。优先选择官方镜像和轻量级发行版:
<span class="c"># ❌ 不推荐:完整的 Ubuntu 镜像,约 100MB+</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">ubuntu:22.04</span>
<span class="c"># ✅ 推荐:Alpine 镜像,约 5MB</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">alpine:3.19</span>
<span class="c"># ✅ 推荐:针对特定语言的 slim 版本</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">python:3.11-slim</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">node:20-alpine</span>
选型建议: – Alpine:体积最小,适合大多数场景,但 musl libc 可能存在兼容性问题 – slim:基于 Debian 的精简版,glibc 兼容性好,体积适中 – distroless:Google 推出的无发行版镜像,只包含应用和依赖,攻击面最小
1.2 多阶段构建(Multi-stage Build)
多阶段构建是减小镜像体积的利器,将编译环境和运行环境分离:
<span class="c"># 构建阶段:包含完整的编译工具链</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">golang:1.21-alpine</span>
<span class="w"> </span>
<span class="k">AS</span>
<span class="w"> </span>
<span class="s">builder</span>
<span class="k">WORKDIR</span>
<span class="w"> </span>
<span class="s">/app</span>
<span class="k">COPY</span>
<span class="w"> </span>go.mod<span class="w"> </span>go.sum<span class="w"> </span>./
<span class="k">RUN</span>
<span class="w"> </span>go<span class="w"> </span>mod<span class="w"> </span>download
<span class="k">COPY</span>
<span class="w"> </span>.<span class="w"> </span>.
<span class="k">RUN</span>
<span class="w"> </span>
<span class="nv">CGO_ENABLED</span>
<span class="o">=</span>
<span class="m">0</span>
<span class="w"> </span>
<span class="nv">GOOS</span>
<span class="o">=</span>linux<span class="w"> </span>go<span class="w"> </span>build<span class="w"> </span>-o<span class="w"> </span>myapp<span class="w"> </span>.
<span class="c"># 运行阶段:只包含编译后的二进制文件</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">alpine:3.19</span>
<span class="k">RUN</span>
<span class="w"> </span>apk<span class="w"> </span>--no-cache<span class="w"> </span>add<span class="w"> </span>ca-certificates
<span class="k">WORKDIR</span>
<span class="w"> </span>
<span class="s">/app</span>
<span class="k">COPY</span>
<span class="w"> </span>--from<span class="o">=</span>builder<span class="w"> </span>/app/myapp<span class="w"> </span>.
<span class="k">EXPOSE</span>
<span class="w"> </span>
<span class="s">8080</span>
<span class="k">CMD</span>
<span class="w"> </span>
<span class="p">[</span>
<span class="s2">"./myapp"</span>
<span class="p">]</span>
通过多阶段构建,最终镜像只包含运行所需的文件,体积可从数百 MB 降至十几 MB 甚至更小。
1.3 层缓存优化
Docker 采用分层存储机制,合理安排指令顺序可以充分利用缓存:
<span class="c"># ❌ 不推荐:每次代码变更都会导致依赖重新下载</span>
<span class="k">COPY</span>
<span class="w"> </span>.<span class="w"> </span>.
<span class="k">RUN</span>
<span class="w"> </span>npm<span class="w"> </span>install
<span class="c"># ✅ 推荐:先复制依赖文件,充分利用缓存</span>
<span class="k">COPY</span>
<span class="w"> </span>package*.json<span class="w"> </span>./
<span class="k">RUN</span>
<span class="w"> </span>npm<span class="w"> </span>install
<span class="k">COPY</span>
<span class="w"> </span>.<span class="w"> </span>.
优化原则: 1. 将变化频率低的指令放在前面(如安装依赖) 2. 将变化频率高的指令放在后面(如复制源代码) 3. 合并同类指令,减少镜像层数
1.4 清理构建产物
安装依赖后及时清理缓存和临时文件:
<span class="c"># Alpine 系统</span>
<span class="k">RUN</span>
<span class="w"> </span>apk<span class="w"> </span>add<span class="w"> </span>--no-cache<span class="w"> </span>curl<span class="w"> </span>nginx
<span class="c"># Debian/Ubuntu 系统</span>
<span class="k">RUN</span>
<span class="w"> </span>apt-get<span class="w"> </span>update<span class="w"> </span>
<span class="o">&&</span>
<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>-y<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>curl<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>nginx<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>
<span class="o">&&</span>
<span class="w"> </span>rm<span class="w"> </span>-rf<span class="w"> </span>/var/lib/apt/lists/*
<span class="c"># npm/yarn 安装后清理</span>
<span class="k">RUN</span>
<span class="w"> </span>npm<span class="w"> </span>install<span class="w"> </span>--production<span class="w"> </span>
<span class="o">&&</span>
<span class="w"> </span>npm<span class="w"> </span>cache<span class="w"> </span>clean<span class="w"> </span>--force
<span class="c"># pip 安装后清理</span>
<span class="k">RUN</span>
<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>--no-cache-dir<span class="w"> </span>-r<span class="w"> </span>requirements.txt
二、容器安全配置最佳实践
安全是生产环境的重中之重,容器的安全配置需要从多个维度入手。
2.1 以非 root 用户运行
默认情况下容器以 root 用户运行,这存在安全风险。应创建专用用户:
<span class="c"># 创建用户和用户组</span>
<span class="k">RUN</span>
<span class="w"> </span>addgroup<span class="w"> </span>-g<span class="w"> </span>
<span class="m">1001</span>
<span class="w"> </span>appgroup<span class="w"> </span>
<span class="o">&&</span>
<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>adduser<span class="w"> </span>-u<span class="w"> </span>
<span class="m">1001</span>
<span class="w"> </span>-G<span class="w"> </span>appgroup<span class="w"> </span>-s<span class="w"> </span>/bin/sh<span class="w"> </span>-D<span class="w"> </span>appuser
<span class="c"># 切换到非 root 用户</span>
<span class="k">USER</span>
<span class="w"> </span>
<span class="s">appuser</span>
运行时也可以通过 --user 参数指定用户:
docker<span class="w"> </span>run<span class="w"> </span>--user<span class="w"> </span>
<span class="m">1001</span>:1001<span class="w"> </span>myapp:latest
2.2 禁用特权模式和能力限制
除非绝对必要,否则不要使用 --privileged 模式。精确控制容器的 Linux capabilities:
<span class="c1"># 丢弃所有能力,只添加必需的</span>
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--cap-drop<span class="w"> </span>ALL<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--cap-add<span class="w"> </span>NET_BIND_SERVICE<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--cap-add<span class="w"> </span>CHOWN<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
常用能力说明: – NET_BIND_SERVICE:允许绑定 1024 以下的端口
– CHOWN:允许修改文件所有者
– DAC_OVERRIDE:绕过文件权限检查(尽量避免)
2.3 只读文件系统
将容器根文件系统设为只读,防止攻击者篡改容器内文件:
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--read-only<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--tmpfs<span class="w"> </span>/tmp<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--tmpfs<span class="w"> </span>/run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
对于需要写入的目录,使用 tmpfs 或挂载数据卷。
2.4 镜像安全扫描
在 CI/CD 流程中集成镜像扫描,及时发现漏洞:
<span class="c1"># 使用 Trivy 扫描镜像</span>
trivy<span class="w"> </span>image<span class="w"> </span>myapp:latest
<span class="c1"># 只显示高危以上漏洞</span>
trivy<span class="w"> </span>image<span class="w"> </span>--severity<span class="w"> </span>HIGH,CRITICAL<span class="w"> </span>myapp:latest
<span class="c1"># 生成 JSON 报告</span>
trivy<span class="w"> </span>image<span class="w"> </span>--format<span class="w"> </span>json<span class="w"> </span>--output<span class="w"> </span>report.json<span class="w"> </span>myapp:latest
推荐工具:Trivy、Aqua、Clair
2.5 镜像签名与验证
使用 Docker Content Trust 确保镜像完整性:
<span class="c1"># 启用 DCT</span>
<span class="nb">export</span>
<span class="w"> </span>
<span class="nv">DOCKER_CONTENT_TRUST</span>
<span class="o">=</span>
<span class="m">1</span>
<span class="c1"># 签名并推送镜像</span>
docker<span class="w"> </span>push<span class="w"> </span>myregistry/myapp:latest
<span class="c1"># 拉取时自动验证签名</span>
docker<span class="w"> </span>pull<span class="w"> </span>myregistry/myapp:latest
三、资源限制与性能优化
合理的资源限制能防止单个容器影响整个宿主机的稳定性。
3.1 内存限制
<span class="c1"># 限制内存使用为 512MB,swap 也限制为 512MB(总内存 1GB)</span>
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--memory<span class="w"> </span>512m<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--memory-swap<span class="w"> </span>1g<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
注意事项: – --memory 设置物理内存限制
– --memory-swap 设置内存 + swap 总和
– 建议设置 --memory-swappiness=0 禁用 swap,避免性能下降
3.2 CPU 限制
<span class="c1"># 限制最多使用 1.5 个 CPU 核心</span>
docker<span class="w"> </span>run<span class="w"> </span>--cpus<span class="w"> </span>
<span class="m">1</span>.5<span class="w"> </span>myapp:latest
<span class="c1"># 使用 CPU 份额(相对权重,默认 1024)</span>
docker<span class="w"> </span>run<span class="w"> </span>--cpu-shares<span class="w"> </span>
<span class="m">512</span>
<span class="w"> </span>myapp:latest
<span class="c1"># 绑定到特定 CPU 核心</span>
docker<span class="w"> </span>run<span class="w"> </span>--cpuset-cpus<span class="w"> </span>
<span class="m">0</span>,1<span class="w"> </span>myapp:latest
3.3 磁盘 I/O 限制
<span class="c1"># 限制磁盘读写速率</span>
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--device-read-bps<span class="w"> </span>/dev/sda:10mb<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--device-write-bps<span class="w"> </span>/dev/sda:10mb<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
3.4 健康检查配置
配置健康检查让 Docker 能够自动检测容器状态:
<span class="k">HEALTHCHECK</span>
<span class="w"> </span>--interval<span class="o">=</span>30s<span class="w"> </span>--timeout<span class="o">=</span>3s<span class="w"> </span>--retries<span class="o">=</span>
<span class="m">3</span>
<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>
<span class="k">CMD</span>
<span class="w"> </span>curl<span class="w"> </span>-f<span class="w"> </span>http://localhost:8080/health<span class="w"> </span>
<span class="o">||</span>
<span class="w"> </span>
<span class="nb">exit</span>
<span class="w"> </span>
<span class="m">1</span>
参数说明: – --interval:检查间隔,默认 30s
– --timeout:超时时间,默认 30s
– --retries:重试次数,默认 3 次
– --start-period:启动宽限期,给应用启动时间
配合 --restart always 或 on-failure 实现自动重启:
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--restart<span class="w"> </span>unless-stopped<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--restart-max-attempts<span class="w"> </span>
<span class="m">5</span>
<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
四、网络配置最佳实践
4.1 使用自定义网络
不要使用默认的 bridge 网络,创建自定义网络实现容器间 DNS 解析和隔离:
<span class="c1"># 创建自定义网络</span>
docker<span class="w"> </span>network<span class="w"> </span>create<span class="w"> </span>--driver<span class="w"> </span>bridge<span class="w"> </span>app-network
<span class="c1"># 运行容器并加入网络</span>
docker<span class="w"> </span>run<span class="w"> </span>--network<span class="w"> </span>app-network<span class="w"> </span>--name<span class="w"> </span>web<span class="w"> </span>nginx
docker<span class="w"> </span>run<span class="w"> </span>--network<span class="w"> </span>app-network<span class="w"> </span>--name<span class="w"> </span>api<span class="w"> </span>myapp
<span class="c1"># 容器间可以通过名称互相访问</span>
<span class="c1"># 在 api 容器中可以直接访问 http://web</span>
4.2 网络模式选择
| 网络模式 | 适用场景 | 特点 |
|---|---|---|
| bridge | 单主机容器通信 | 默认模式,隔离性好 |
| host | 高性能网络需求 | 共享宿主机网络栈,性能最好 |
| overlay | 多主机集群 | 跨主机容器通信 |
| macvlan | 需要独立 MAC 地址 | 容器有独立 MAC,像物理机一样 |
| none | 完全隔离 | 无网络,安全等级最高 |
4.3 端口映射安全
<span class="c1"># ❌ 不推荐:绑定到所有接口</span>
docker<span class="w"> </span>run<span class="w"> </span>-p<span class="w"> </span>
<span class="m">8080</span>:8080<span class="w"> </span>myapp
<span class="c1"># ✅ 推荐:只绑定到 localhost</span>
docker<span class="w"> </span>run<span class="w"> </span>-p<span class="w"> </span>
<span class="m">127</span>.0.0.1:8080:8080<span class="w"> </span>myapp
<span class="c1"># ✅ 推荐:指定特定网卡</span>
docker<span class="w"> </span>run<span class="w"> </span>-p<span class="w"> </span>
<span class="m">192</span>.168.1.100:8080:8080<span class="w"> </span>myapp
五、数据持久化与存储
5.1 使用数据卷(Volume)
数据卷是 Docker 推荐的持久化方式,性能好且易于管理:
<span class="c1"># 创建命名卷</span>
docker<span class="w"> </span>volume<span class="w"> </span>create<span class="w"> </span>app-data
<span class="c1"># 使用数据卷</span>
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>-v<span class="w"> </span>app-data:/app/data<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
5.2 Bind Mount 使用场景
Bind Mount 适合开发环境和需要访问宿主机特定文件的场景:
<span class="c1"># 开发环境挂载源代码</span>
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>-v<span class="w"> </span>
<span class="k">$(</span>
<span class="nb">pwd</span>
<span class="k">)</span>/src:/app/src<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>-v<span class="w"> </span>
<span class="k">$(</span>
<span class="nb">pwd</span>
<span class="k">)</span>/config:/app/config:ro<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
注意: 使用 :ro 只读挂载,防止容器修改宿主机文件。
5.3 tmpfs 临时文件系统
对于不需要持久化的临时数据,使用 tmpfs 提升性能:
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--tmpfs<span class="w"> </span>/tmp:rw,size<span class="o">=</span>64m<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--tmpfs<span class="w"> </span>/run:rw,size<span class="o">=</span>32m<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
六、日志管理最佳实践
6.1 日志输出到 stdout/stderr
容器内的应用应该将日志输出到标准输出,而不是写入文件:
<span class="c"># Nginx 配置示例:将日志输出到 stdout/stderr</span>
<span class="k">RUN</span>
<span class="w"> </span>ln<span class="w"> </span>-sf<span class="w"> </span>/dev/stdout<span class="w"> </span>/var/log/nginx/access.log<span class="w"> </span>
<span class="o">&&</span>
<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>ln<span class="w"> </span>-sf<span class="w"> </span>/dev/stderr<span class="w"> </span>/var/log/nginx/error.log
6.2 配置日志驱动
Docker 支持多种日志驱动,生产环境建议限制日志大小:
<span class="c1"># 限制单个容器日志大小,防止磁盘占满</span>
docker<span class="w"> </span>run<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--log-driver<span class="w"> </span>json-file<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--log-opt<span class="w"> </span>max-size<span class="o">=</span>10m<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>--log-opt<span class="w"> </span>max-file<span class="o">=</span>
<span class="m">3</span>
<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>myapp:latest
常用日志驱动: – json-file:默认,JSON 格式存储
– syslog:发送到 syslog
– journald:发送到 systemd journal
– fluentd:发送到 Fluentd
– awslogs:发送到 AWS CloudWatch
6.3 全局日志配置
在 /etc/docker/daemon.json 中配置全局默认值:
<span class="p">{</span>
<span class="w"> </span>
<span class="nt">"log-driver"</span>
<span class="p">:</span>
<span class="w"> </span>
<span class="s2">"json-file"</span>
<span class="p">,</span>
<span class="w"> </span>
<span class="nt">"log-opts"</span>
<span class="p">:</span>
<span class="w"> </span>
<span class="p">{</span>
<span class="w"> </span>
<span class="nt">"max-size"</span>
<span class="p">:</span>
<span class="w"> </span>
<span class="s2">"10m"</span>
<span class="p">,</span>
<span class="w"> </span>
<span class="nt">"max-file"</span>
<span class="p">:</span>
<span class="w"> </span>
<span class="s2">"3"</span>
<span class="w"> </span>
<span class="p">}</span>
<span class="p">}</span>
七、生产环境部署清单
7.1 安全检查清单
- [ ] 镜像使用官方或可信来源
- [ ] 镜像经过安全扫描,无高危漏洞
- [ ] 容器以非 root 用户运行
- [ ] 禁用不必要的 Linux capabilities
- [ ] 根文件系统只读
- [ ] 不使用特权模式
- [ ] 镜像启用签名验证
7.2 资源配置清单
- [ ] 设置合理的内存限制
- [ ] 设置合理的 CPU 限制
- [ ] 配置健康检查
- [ ] 配置重启策略
- [ ] 限制日志文件大小
7.3 运维最佳实践
- 使用固定标签:生产环境不要使用
latest标签,使用具体版本号 - 资源监控:部署 cAdvisor、Prometheus 等监控工具
- 定期更新:及时更新基础镜像和应用镜像
- 备份策略:定期备份数据卷
- 编排工具:生产环境使用 Kubernetes、Docker Swarm 等编排工具
八、实战:一个生产级 Dockerfile 示例
下面是一个 Go 应用的生产级 Dockerfile,综合了上述最佳实践:
<span class="c"># ========== 构建阶段 ==========</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">golang:1.21-alpine</span>
<span class="w"> </span>
<span class="k">AS</span>
<span class="w"> </span>
<span class="s">builder</span>
<span class="c"># 安装构建依赖</span>
<span class="k">RUN</span>
<span class="w"> </span>apk<span class="w"> </span>add<span class="w"> </span>--no-cache<span class="w"> </span>git<span class="w"> </span>ca-certificates<span class="w"> </span>tzdata
<span class="c"># 创建非 root 用户(用于最终镜像)</span>
<span class="k">RUN</span>
<span class="w"> </span>adduser<span class="w"> </span>-u<span class="w"> </span>
<span class="m">10001</span>
<span class="w"> </span>-D<span class="w"> </span>appuser
<span class="k">WORKDIR</span>
<span class="w"> </span>
<span class="s">/app</span>
<span class="c"># 复制依赖文件,利用缓存</span>
<span class="k">COPY</span>
<span class="w"> </span>go.mod<span class="w"> </span>go.sum<span class="w"> </span>./
<span class="k">RUN</span>
<span class="w"> </span>go<span class="w"> </span>mod<span class="w"> </span>download
<span class="c"># 复制源代码</span>
<span class="k">COPY</span>
<span class="w"> </span>.<span class="w"> </span>.
<span class="c"># 构建二进制文件</span>
<span class="c"># -ldflags="-w -s" 减小二进制体积</span>
<span class="k">RUN</span>
<span class="w"> </span>
<span class="nv">CGO_ENABLED</span>
<span class="o">=</span>
<span class="m">0</span>
<span class="w"> </span>
<span class="nv">GOOS</span>
<span class="o">=</span>linux<span class="w"> </span>
<span class="nv">GOARCH</span>
<span class="o">=</span>amd64<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>go<span class="w"> </span>build<span class="w"> </span>-ldflags<span class="o">=</span>
<span class="s2">"-w -s"</span>
<span class="w"> </span>-o<span class="w"> </span>/go/bin/myapp<span class="w"> </span>.
<span class="c"># ========== 运行阶段 ==========</span>
<span class="k">FROM</span>
<span class="w"> </span>
<span class="s">scratch</span>
<span class="c"># 从构建阶段复制必要文件</span>
<span class="k">COPY</span>
<span class="w"> </span>--from<span class="o">=</span>builder<span class="w"> </span>/usr/share/zoneinfo<span class="w"> </span>/usr/share/zoneinfo
<span class="k">COPY</span>
<span class="w"> </span>--from<span class="o">=</span>builder<span class="w"> </span>/etc/ssl/certs/ca-certificates.crt<span class="w"> </span>/etc/ssl/certs/
<span class="k">COPY</span>
<span class="w"> </span>--from<span class="o">=</span>builder<span class="w"> </span>/etc/passwd<span class="w"> </span>/etc/passwd
<span class="k">COPY</span>
<span class="w"> </span>--from<span class="o">=</span>builder<span class="w"> </span>/etc/group<span class="w"> </span>/etc/group
<span class="k">COPY</span>
<span class="w"> </span>--from<span class="o">=</span>builder<span class="w"> </span>/go/bin/myapp<span class="w"> </span>/myapp
<span class="c"># 使用非 root 用户</span>
<span class="k">USER</span>
<span class="w"> </span>
<span class="s">appuser:appuser</span>
<span class="c"># 健康检查</span>
<span class="k">HEALTHCHECK</span>
<span class="w"> </span>--interval<span class="o">=</span>30s<span class="w"> </span>--timeout<span class="o">=</span>3s<span class="w"> </span>--start-period<span class="o">=</span>5s<span class="w"> </span>--retries<span class="o">=</span>
<span class="m">3</span>
<span class="w"> </span>
<span class="se">\</span>
<span class="w"> </span>CMD<span class="w"> </span>
<span class="o">[</span>
<span class="s2">"/myapp"</span>,<span class="w"> </span>
<span class="s2">"healthcheck"</span>
<span class="o">]</span>
<span class="w"> </span>
<span class="o">||</span>
<span class="w"> </span>
<span class="nb">exit</span>
<span class="w"> </span>
<span class="m">1</span>
<span class="c"># 暴露端口</span>
<span class="k">EXPOSE</span>
<span class="w"> </span>
<span class="s">8080</span>
<span class="c"># 启动命令</span>
<span class="k">ENTRYPOINT</span>
<span class="w"> </span>
<span class="p">[</span>
<span class="s2">"/myapp"</span>
<span class="p">]</span>
<span class="k">CMD</span>
<span class="w"> </span>
<span class="p">[</span>
<span class="s2">"serve"</span>
<span class="p">]</span>
这个 Dockerfile 构建出的镜像体积通常只有 10~20MB,且安全性极高。
九、总结
Docker 容器化看似简单,但要在生产环境稳定运行,需要关注镜像优化、安全配置、资源管理、网络存储等多个方面。本文总结的最佳实践涵盖了从开发构建到生产部署的全流程,建议按照以下优先级逐步落地:
- 基础优化:多阶段构建、层缓存优化、清理构建产物
- 安全加固:非 root 用户、能力限制、只读文件系统、镜像扫描
- 资源管控:内存/CPU 限制、健康检查、重启策略
- 运维完善:日志管理、监控告警、备份策略
容器化是一个持续优化的过程,建议结合自身业务特点,在实践中不断调整和完善。