引言
编写高质量的Dockerfile是容器化的关键。本文介绍Dockerfile的最佳实践。
一、基础优化
1.1 选择合适的基础镜像
1 2 3 4 5 6 7 8
| FROM ubuntu:latest
FROM alpine:3.18
FROM node:18-alpine
|
1.2 合并RUN指令
1 2 3 4 5 6 7 8 9 10
| RUN apt-get update RUN apt-get install -y curl RUN apt-get clean
RUN apt-get update && \ apt-get install -y curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*
|
1.3 使用.dockerignore
1 2 3 4 5 6 7
| node_modules npm-debug.log .git .gitignore .env *.md .DS_Store
|
二、多阶段构建
2.1 Java应用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| FROM maven:3.8-jdk-11 AS builder WORKDIR /build COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests
FROM openjdk:11-jre-slim WORKDIR /app COPY --from=builder /build/target/app.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
|
2.2 Node.js应用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| FROM node:18-alpine AS builder WORKDIR /build COPY package*.json ./ RUN npm ci --only=production COPY . . RUN npm run build
FROM node:18-alpine WORKDIR /app COPY --from=builder /build/dist ./dist COPY --from=builder /build/node_modules ./node_modules EXPOSE 3000 CMD ["node", "dist/main.js"]
|
三、安全加固
3.1 使用非root用户
1 2 3 4 5 6 7 8 9 10 11 12 13
| FROM node:18-alpine
RUN addgroup -g 1001 appgroup && \ adduser -D -u 1001 -G appgroup appuser
WORKDIR /app COPY --chown=appuser:appgroup . .
USER appuser
CMD ["node", "index.js"]
|
3.2 最小化暴露
1 2 3 4 5 6 7 8
| EXPOSE 8080
RUN apt-get update && \ apt-get install -y --no-install-recommends \ curl && \ apt-get clean
|
四、性能优化
4.1 利用构建缓存
1 2 3 4 5 6
| COPY package*.json ./ RUN npm install
COPY . .
|
4.2 优化层顺序
1 2 3 4 5 6 7 8 9 10 11 12
| FROM node:18-alpine WORKDIR /app
COPY package*.json ./ RUN npm install
COPY . .
CMD ["node", "index.js"]
|
五、健康检查
1 2 3 4 5 6 7
| HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1
HEALTHCHECK --interval=30s --timeout=3s \ CMD nc -z localhost 8080 || exit 1
|
六、完整示例
6.1 Spring Boot应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| FROM maven:3.8-jdk-11-slim AS builder WORKDIR /build
COPY pom.xml . RUN mvn dependency:go-offline -B
COPY src ./src RUN mvn package -DskipTests -B
FROM openjdk:11-jre-slim LABEL maintainer="your@email.com"
RUN groupadd -r spring && useradd -r -g spring spring
WORKDIR /app
COPY --from=builder --chown=spring:spring \ /build/target/*.jar app.jar
USER spring
ENV JAVA_OPTS="-Xms256m -Xmx512m"
HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
|
6.2 前端应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| FROM node:18-alpine AS builder WORKDIR /build
COPY package*.json ./ RUN npm ci --only=production
COPY . . RUN npm run build
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /build/dist /usr/share/nginx/html
HEALTHCHECK --interval=30s --timeout=3s \ CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
|
七、常用技巧
7.1 ARG与ENV
1 2 3 4 5 6 7 8 9 10
| ARG VERSION=1.0.0 ARG BUILD_DATE
ENV APP_VERSION=${VERSION} ENV BUILD_DATE=${BUILD_DATE}
LABEL version="${VERSION}" \ build-date="${BUILD_DATE}"
|
7.2 ENTRYPOINT vs CMD
1 2 3 4 5 6 7
| ENTRYPOINT ["java", "-jar"]
CMD ["app.jar"]
|
总结
Dockerfile最佳实践:
- 选择合适的基础镜像:轻量级优先
- 多阶段构建:减小镜像体积
- 安全加固:非root用户、最小化暴露
- 利用缓存:优化构建速度
- 健康检查:保证容器可用性
参考资料