使用 Docker 容器部署
构建、优化和部署 Web 应用的多阶段 Docker 镜像,遵循安全最佳实践。
为什么
Docker 容器将应用与所有依赖打包,确保开发、预发布和生产环境行为一致。多阶段构建将镜像大小减少 80% 以上,并将构建工具与运行时隔离。
Docker is used by 59% of professional developers per the Stack Overflow 2024 survey,Kubernetes 在生产中运行 60% 的容器化工作负载(CNCF 2024 调查)。容器编排通过声明式滚动发布将部署相关事故减少 35%。
何时使用
部署到 Kubernetes、ECS 或任何容器编排平台时使用 Docker。也适用于本地开发一致性和 CI 可复现性。
如何做
示例
常见问题
- ⚠镜像 1.5GB — 用 node:20(完整 Debian)而非 node:20-alpine 或多阶段
- ⚠每次构建缓存失效 — COPY . . 在 COPY package.json 前破坏层缓存
- ⚠以 root 运行 — 容器逃逸给攻击者 host root 权限,始终用 USER 指令
- ⚠密钥烤入镜像 — ENV 设置 API key 意味着任何拿到镜像的人都能提取
最佳实践
- ✓使用多阶段构建 — 最终镜像不应包含 npm、tsc 或源文件
- ✓固定基础镜像摘要 — FROM node:20-alpine@sha256:abc... 而非仅 :20-alpine
- ✓使用 BuildKit — DOCKER_BUILDKIT=1 并行阶段构建和缓存挂载
- ✓CI 中扫描每个镜像 — trivy image myapp:latest,HIGH/CRITICAL CVE 时失败
常见问题解答
为什么 Docker 镜像 1.2 GB?
用了完整 Node 基础镜像(node:18)而非 node:18-alpine。换 alpine 并加 .dockerignore 排除 node_modules、.git、测试——镜像降到 ~120 MB。
如何在 Docker 中缓存 node_modules?
先复制 package.json 和 lockfile,跑 npm ci,再复制其余。lockfile 未变时 Docker 层缓存跳过安装,重建从 60s 降到 5s。
容器内该用 root 运行吗?
不该——创建非 root 用户(USER node)并设文件归属。容器内 root 逃逸后即宿主 root。node:18-alpine 基础镜像含 node 用户。
为什么容器报 EADDRINUSE 崩溃?
应用监听容器内已占用端口。用 env 的 PORT(process.env.PORT)并 EXPOSE 该端口。别硬编码 3000——编排器分配动态端口。
如何调试立即退出的容器?
运行 docker run --entrypoint sh <image> 获取 shell。docker logs <id> 查日志。常见原因:缺环境变量、CMD 错误、OOM。