Files
cs-note/hzh/MS/05-部署运维/01-容器化.md
T
2026-05-24 11:42:38 +08:00

156 lines
4.1 KiB
Markdown
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.
---
tags: [microservice, docker, container, image-optimization]
create time: 2026-05-05
---
# 容器化
## 概述
Docker 容器是微服务交付的标准单元。它解决了"在我机器上是好的"这个经典问题——**开发、测试、生产使用完全一致的运行时环境**。
```mermaid
graph TB
CODE["源代码"] --> BUILD["CI 构建镜像"]
BUILD --> REGISTRY["镜像仓库<br/>Harbor / ECR / ACR"]
REGISTRY --> K8s["Kubernetes 部署"]
style BUILD fill:#e3f2fd
style REGISTRY fill:#fff3e0
style K8s fill:#e8f5e9
```
## Dockerfile 最佳实践
### Go 多阶段构建(推荐)
```dockerfile
# ========== 阶段 1: 构建 ==========
FROM golang:1.22-alpine AS builder
RUN apk --no-cache add git ca-certificates
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
ARG LDFLAGS="-s -w -extldflags '-static'"
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "$LDFLAGS" -o server .
# ========== 阶段 2: 运行时 ==========
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget -qO- http://localhost:8080/healthz || exit 1
CMD ["./server"]
```
### 关键优化点
| 优化项 | 方法 | 效果 |
|--------|------|------|
| **多阶段构建** | 编译和运行分离 | 镜像从 800MB → 15MB |
| **alpine 基础镜像** | 替代 debian/ubuntu | 减小体积 |
| **非 root 运行** | `USER appuser` | 安全合规 |
| **静态链接** | `CGO_ENABLED=0` | 不依赖系统库 |
| **layer cache** | `go.mod` 先 COPY | CI 加速构建 |
| **健康检查** | HEALTHCHECK 指令 | K8s 原生支持 |
### `.dockerignore`
```
.git
.gitignore
*.md
vendor/
tests/
*.log
.DS_Store
.idea/
.vscode/
```
> [!tip] 为什么 .dockerignore 很重要?
>
> 如果不排除 `.git` 目录,整个版本历史都会被打包进镜像(增加数百 MB)。如果排除不当,可能遗漏必要的配置文件。
## 镜像安全
```mermaid
flowchart LR
Scan["镜像扫描 (Trivy/Snyk)"] --> Clean{"漏洞等级?"}
Clean -- "CRITICAL/HIGH" --> Block["❌ 阻止推送"]
Clean -- "MEDIUM" --> Review["⚠️ 人工审核"]
Clean -- "LOW/INFO" --> Allow["✅ 允许推送"]
style Block fill:#ffebee
style Review fill:#fff3e0
style Allow fill:#e8f5e9
```
### 安全检查清单
- [ ] 不使用 `latest` tag(永远用具体版本号)
- [ ] 不安装不必要的软件包(`apk del --purge .build-deps`)
- [ ] 定期更新基础镜像(修复 CVE)
- [ ] 使用非 root 用户运行
- [ ] 镜像不包含密钥、密码、私钥
- [ ] 使用最小基础镜像(scratch / distroless)
### Distroless 镜像
Google 推出的**无 shell、无包管理器**的极简运行时镜像:
```dockerfile
# 最极致的精简
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server .
USER nonroot
CMD ["./server"]
```
> ⚠️ 注意:distroless 镜像没有 shell (`/bin/sh`),调试时需要额外工具(如 debug 镜像或 `kubectl exec` 到 sidecar)。
## 镜像仓库管理
```mermaid
flowchart LR
Dev["开发者本地"] -->|"docker push"| DEV_REPO["dev 仓库<br/>v1.2.3-dev"]
Staging["Staging 验证"] -->|"通过"| PROD_REPO["prod 仓库<br/>v1.2.3"]
K8s["K8s Cluster"] -->|"pull"| PROD_REPO
PR["PR Merge"] --> Tag["打标签 v1.2.3"]
Tag --> ProdRepoMove["移动到 prod 仓库"]
style DEV_REPO fill:#fff3e0
style PROD_REPO fill:#e8f5e9
```
| 仓库方案 | 特点 | 适用场景 |
|---------|------|---------|
| **Harbor** | 自托管,RBAC + 扫描 | 国内企业首选 |
| **ECR / ACR / GCR** | 云厂商托管 | 全云环境 |
| **Docker Hub** | 公共免费 | 开源项目 |
## 关联笔记
- [[05-部署运维/02-Kubernetes]] — K8s 以 Pod 为部署单元,镜像来自 Docker
- [[05-部署运维/03-CICD与GitOps]] — CI/CD 流水线中的镜像构建环节