dockerfile
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDockerfile 编写
Dockerfile 编写
概述
概述
Dockerfile 最佳实践、安全扫描等技能。
Dockerfile 最佳实践、安全扫描等技能。
指令详解
指令详解
FROM
FROM
dockerfile
undefineddockerfile
undefined基础镜像
基础镜像
FROM ubuntu:22.04
FROM node:18-alpine
FROM python:3.11-slim
FROM ubuntu:22.04
FROM node:18-alpine
FROM python:3.11-slim
多阶段构建
多阶段构建
FROM node:18 AS builder
FROM nginx:alpine AS production
FROM node:18 AS builder
FROM nginx:alpine AS production
使用 ARG 动态指定
使用 ARG 动态指定
ARG BASE_IMAGE=node:18-alpine
FROM ${BASE_IMAGE}
undefinedARG BASE_IMAGE=node:18-alpine
FROM ${BASE_IMAGE}
undefinedWORKDIR
WORKDIR
dockerfile
undefineddockerfile
undefined设置工作目录(推荐使用绝对路径)
设置工作目录(推荐使用绝对路径)
WORKDIR /app
WORKDIR /home/node/app
WORKDIR /app
WORKDIR /home/node/app
多次使用会切换目录
多次使用会切换目录
WORKDIR /app
WORKDIR src
WORKDIR /app
WORKDIR src
当前目录: /app/src
当前目录: /app/src
undefinedundefinedCOPY 与 ADD
COPY 与 ADD
dockerfile
undefineddockerfile
undefinedCOPY(推荐)
COPY(推荐)
COPY package.json ./
COPY src/ ./src/
COPY --chown=node:node . .
COPY package.json ./
COPY src/ ./src/
COPY --chown=node:node . .
多文件复制
多文件复制
COPY package.json package-lock.json ./
COPY package.json package-lock.json ./
ADD(支持 URL 和解压)
ADD(支持 URL 和解压)
ADD https://example.com/file.tar.gz /app/
ADD archive.tar.gz /app/ # 自动解压
ADD https://example.com/file.tar.gz /app/
ADD archive.tar.gz /app/ # 自动解压
推荐:优先使用 COPY,除非需要 ADD 的特殊功能
推荐:优先使用 COPY,除非需要 ADD 的特殊功能
undefinedundefinedRUN
RUN
dockerfile
undefineddockerfile
undefinedShell 形式
Shell 形式
RUN apt-get update && apt-get install -y curl
RUN apt-get update && apt-get install -y curl
Exec 形式
Exec 形式
RUN ["apt-get", "update"]
RUN ["apt-get", "update"]
最佳实践:合并命令减少层数
最佳实践:合并命令减少层数
RUN apt-get update &&
apt-get install -y --no-install-recommends
curl
wget
git &&
rm -rf /var/lib/apt/lists/*
apt-get install -y --no-install-recommends
curl
wget
git &&
rm -rf /var/lib/apt/lists/*
undefinedRUN apt-get update &&
apt-get install -y --no-install-recommends
curl
wget
git &&
rm -rf /var/lib/apt/lists/*
apt-get install -y --no-install-recommends
curl
wget
git &&
rm -rf /var/lib/apt/lists/*
undefinedCMD 与 ENTRYPOINT
CMD 与 ENTRYPOINT
dockerfile
undefineddockerfile
undefinedCMD - 默认命令(可被覆盖)
CMD - 默认命令(可被覆盖)
CMD ["node", "app.js"]
CMD ["npm", "start"]
CMD ["node", "app.js"]
CMD ["npm", "start"]
ENTRYPOINT - 入口点(不易被覆盖)
ENTRYPOINT - 入口点(不易被覆盖)
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]
组合使用
组合使用
ENTRYPOINT ["python"]
CMD ["app.py"]
ENTRYPOINT ["python"]
CMD ["app.py"]
运行: python app.py
运行: python app.py
docker run myimage other.py -> python other.py
docker run myimage other.py -> python other.py
undefinedundefinedENV 与 ARG
ENV 与 ARG
dockerfile
undefineddockerfile
undefinedENV - 运行时环境变量
ENV - 运行时环境变量
ENV NODE_ENV=production
ENV PORT=3000 HOST=0.0.0.0
ENV NODE_ENV=production
ENV PORT=3000 HOST=0.0.0.0
ARG - 构建时参数
ARG - 构建时参数
ARG VERSION=1.0
ARG BUILD_DATE
ARG VERSION=1.0
ARG BUILD_DATE
ARG 转 ENV
ARG 转 ENV
ARG APP_VERSION
ENV APP_VERSION=${APP_VERSION}
ARG APP_VERSION
ENV APP_VERSION=${APP_VERSION}
使用构建参数
使用构建参数
docker build --build-arg VERSION=2.0 .
docker build --build-arg VERSION=2.0 .
undefinedundefinedEXPOSE
EXPOSE
dockerfile
undefineddockerfile
undefined声明端口(文档作用)
声明端口(文档作用)
EXPOSE 80
EXPOSE 443
EXPOSE 3000/tcp
EXPOSE 5000/udp
undefinedEXPOSE 80
EXPOSE 443
EXPOSE 3000/tcp
EXPOSE 5000/udp
undefinedVOLUME
VOLUME
dockerfile
undefineddockerfile
undefined声明挂载点
声明挂载点
VOLUME /data
VOLUME ["/data", "/logs"]
undefinedVOLUME /data
VOLUME ["/data", "/logs"]
undefinedUSER
USER
dockerfile
undefineddockerfile
undefined切换用户
切换用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
或使用 UID
或使用 UID
USER 1000:1000
undefinedUSER 1000:1000
undefinedHEALTHCHECK
HEALTHCHECK
dockerfile
undefineddockerfile
undefined健康检查
健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD curl -f http://localhost/ || exit 1
CMD curl -f http://localhost/ || exit 1
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD curl -f http://localhost/ || exit 1
CMD curl -f http://localhost/ || exit 1
禁用健康检查
禁用健康检查
HEALTHCHECK NONE
undefinedHEALTHCHECK NONE
undefined最佳实践模板
最佳实践模板
Node.js 应用
Node.js 应用
dockerfile
FROM node:18-alpinedockerfile
FROM node:18-alpine创建非 root 用户
创建非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
先复制依赖文件
先复制依赖文件
COPY package*.json ./
COPY package*.json ./
安装依赖
安装依赖
RUN npm ci --only=production && npm cache clean --force
RUN npm ci --only=production && npm cache clean --force
复制源代码
复制源代码
COPY --chown=appuser:appgroup . .
COPY --chown=appuser:appgroup . .
切换用户
切换用户
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "app.js"]
undefinedUSER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "app.js"]
undefinedPython 应用
Python 应用
dockerfile
FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /appdockerfile
FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app安装依赖
安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
创建非 root 用户
创建非 root 用户
RUN useradd -m -r appuser && chown appuser:appuser /app
USER appuser
COPY --chown=appuser:appuser . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
undefinedRUN useradd -m -r appuser && chown appuser:appuser /app
USER appuser
COPY --chown=appuser:appuser . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
undefinedGo 应用
Go 应用
dockerfile
undefineddockerfile
undefined构建阶段
构建阶段
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o main .
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o main .
生产阶段
生产阶段
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/main /main
EXPOSE 8080
ENTRYPOINT ["/main"]
undefinedFROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/main /main
EXPOSE 8080
ENTRYPOINT ["/main"]
undefinedJava 应用
Java 应用
dockerfile
undefineddockerfile
undefined构建阶段
构建阶段
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
生产阶段
生产阶段
FROM eclipse-temurin:17-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
undefinedFROM eclipse-temurin:17-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
undefined.dockerignore
.dockerignore
dockerignore
undefineddockerignore
undefinedGit
Git
.git
.gitignore
.git
.gitignore
Node
Node
node_modules
npm-debug.log
node_modules
npm-debug.log
Python
Python
pycache
*.pyc
.venv
venv
pycache
*.pyc
.venv
venv
IDE
IDE
.idea
.vscode
*.swp
.idea
.vscode
*.swp
Docker
Docker
Dockerfile*
docker-compose*
.dockerignore
Dockerfile*
docker-compose*
.dockerignore
文档
文档
*.md
LICENSE
*.md
LICENSE
测试
测试
test
tests
coverage
test
tests
coverage
其他
其他
.env
.env.*
*.log
tmp
undefined.env
.env.*
*.log
tmp
undefined安全检查
安全检查
镜像扫描
镜像扫描
bash
undefinedbash
undefinedDocker Scout
Docker Scout
docker scout cves myimage:tag
docker scout recommendations myimage:tag
docker scout cves myimage:tag
docker scout recommendations myimage:tag
Trivy
Trivy
trivy image myimage:tag
trivy image myimage:tag
Snyk
Snyk
snyk container test myimage:tag
undefinedsnyk container test myimage:tag
undefinedDockerfile 检查
Dockerfile 检查
bash
undefinedbash
undefinedHadolint
Hadolint
docker run --rm -i hadolint/hadolint < Dockerfile
docker run --rm -i hadolint/hadolint < Dockerfile
Dockle
Dockle
dockle myimage:tag
undefineddockle myimage:tag
undefined常见场景
常见场景
场景 1:入口脚本
场景 1:入口脚本
dockerfile
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["app"]bash
#!/bin/bash
set -edockerfile
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["app"]bash
#!/bin/bash
set -e初始化逻辑
初始化逻辑
if [ "$1" = 'app' ]; then
# 等待依赖服务
until nc -z db 5432; do
echo "Waiting for database..."
sleep 1
done
fi
exec "$@"
undefinedif [ "$1" = 'app' ]; then
# 等待依赖服务
until nc -z db 5432; do
echo "Waiting for database..."
sleep 1
done
fi
exec "$@"
undefined场景 2:多架构构建
场景 2:多架构构建
bash
undefinedbash
undefined创建 builder
创建 builder
docker buildx create --name mybuilder --use
docker buildx create --name mybuilder --use
多架构构建并推送
多架构构建并推送
docker buildx build --platform linux/amd64,linux/arm64
-t myrepo/myimage:tag --push .
-t myrepo/myimage:tag --push .
undefineddocker buildx build --platform linux/amd64,linux/arm64
-t myrepo/myimage:tag --push .
-t myrepo/myimage:tag --push .
undefined场景 3:构建缓存
场景 3:构建缓存
bash
undefinedbash
undefined使用 BuildKit 缓存
使用 BuildKit 缓存
docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t myimage:tag .
docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t myimage:tag .
使用缓存
使用缓存
docker build --cache-from myimage:tag -t myimage:new .
undefineddocker build --cache-from myimage:tag -t myimage:new .
undefined故障排查
故障排查
| 问题 | 排查方法 |
|---|---|
| 构建慢 | 优化 COPY 顺序、使用缓存 |
| 镜像大 | 多阶段构建、精简基础镜像 |
| 权限问题 | 检查 USER、文件权限 |
| 依赖问题 | 检查网络、使用国内镜像源 |
| 问题 | 排查方法 |
|---|---|
| 构建慢 | 优化 COPY 顺序、使用缓存 |
| 镜像大 | 多阶段构建、精简基础镜像 |
| 权限问题 | 检查 USER、文件权限 |
| 依赖问题 | 检查网络、使用国内镜像源 |