Dockerfile 基础
Dockerfile 指令大全
# ============ 基础指令 ============
# FROM: 指定基础镜像
FROM ubuntu:22.04
FROM alpine:3.18
FROM scratch# 空白镜像,用于构建最小镜像
# LABEL: 添加元数据
LABEL maintainer="your-email@example.com"
LABEL version="1.0"
LABEL description="This is a sample image"
# RUN: 执行命令
RUN apt-get update && apt-get install -y \
curl \
vim \
&& rm -rf /var/lib/apt/lists/*
# CMD: 容器启动时的默认命令
CMD ["nginx", "-g", "daemon off;"]
CMD ["python", "app.py"]
CMD echo "Hello World"
# ENTRYPOINT: 容器启动时的入口点
ENTRYPOINT ["python", "app.py"]
ENTRYPOINT ["nginx"]
# ============ 文件操作 ============
# COPY: 从主机复制文件到镜像
COPY app.py /app/
COPY . /app/
COPY --from=builder /app/build /app/
# ADD: 类似 COPY,但支持 URL 和自动解压
ADD https://example.com/file.tar.gz /tmp/
ADD archive.tar.gz /usr/local/# 自动解压
# ============ 环境和配置 ============
# ENV: 设置环境变量
ENV APP_ENV=production
ENV PATH="/app/bin:${PATH}"
ENV \
APP_VERSION=1.0 \
APP_ENV=production
# ARG: 构建时的参数
ARG VERSION=1.0
ARG BASE_IMAGE=ubuntu:22.04
FROM ${BASE_IMAGE}
# WORKDIR: 设置工作目录
WORKDIR /app
WORKDIR /var/www/html
# ============ 端口和用户 ============
# EXPOSE: 声明容器监听的端口
EXPOSE 80 443
EXPOSE 3000
# USER: 指定运行用户
USER nginx
USER 1000:1000
# ============ 卷和触发器 ============
# VOLUME: 创建挂载点
VOLUME ["/data"]
VOLUME ["/var/log/app", "/var/lib/app"]
# ONBUILD: 在子镜像构建时执行
ONBUILD COPY . /app/
ONBUILD RUN pip install -r requirements.txt
# ============ 健康检查 ============
# HEALTHCHECK: 健康检查指令
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost/ || exit 1
HEALTHCHECK NONE# 禁用基础镜像的健康检查
# ============ Shell 和信号 ============
# SHELL: 覆盖默认 shell
SHELL ["/bin/bash", "-c"]
# STOPSIGNAL: 设置停止信号
STOPSIGNAL SIGTERM
STOPSIGNAL 9
________________________________________________________________________________
4.2 Dockerfile 最佳实践
1. 最小化镜像层数
# ❌ 不推荐:多层 RUN
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y vim
RUN rm -rf /var/lib/apt/lists/*
# ✅ 推荐:合并 RUN 指令
RUN apt-get update && apt-get install -y \
curl \
vim \
&& rm -rf /var/lib/apt/lists/*
2. 使用 .dockerignore
# .dockerignore 文件示例
.git
.gitignore
node_modules
npm-debug.log
.env
__pycache__
*.pyc
.vscode
.DS_Store
*.md
tests/
*.test.js
coverage/
3. 优化缓存利用
# ✅ 推荐:将变化少的指令放在前面
FROM node:18-alpine
WORKDIR /app
# 先复制依赖文件(变化少)
COPY package*.json ./
RUN npm ci --only=production
# 再复制源代码(变化多)
COPY . .
CMD ["node", "app.js"]
4. 多阶段构建
# ========== 构建阶段 ==========
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ========== 生产阶段 ==========
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/app.js"]
5. 使用非 root 用户
FROM alpine:3.18
# 安装必要的工具
RUN apk add --no-cache curl
# 创建用户
RUN addgroup -g 1000 appuser && \
adduser -D -u 1000 -G appuser appuser
# 设置工作目录并设置权限
WORKDIR /app
COPY --chown=appuser:appuser . .
# 切换到非 root 用户
USER appuser
CMD ["python", "app.py"]
_________________________
4.3 实战 Dockerfile 示例
示例 1: Node.js 应用
# 多阶段构建
FROM node:18-alpine AS builder
WORKDIR /app
# 安装依赖
COPY package*.json ./
RUN npm ci --only=production
# 复制源代码
COPY . .
# 构建应用
RUN npm run build
# 生产镜像
FROM node:18-alpine
WORKDIR /app
# 从构建阶段复制
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
# 创建非 root 用户
RUN addgroup -g 1000 node && \
adduser -D -u 1000 -G node node
# 设置权限
RUN chown -R node:node /app
USER node
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
CMD ["node", "dist/app.js"]
示例 2: Python 应用
FROM python:3.11-slim
# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
gcc \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# 安装 Python 依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 创建非 root 用户
RUN useradd -m -u 1000 appuser && \
chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
示例 3: Nginx 静态网站
FROM nginx:alpine
# 删除默认配置
RUN rm /etc/nginx/conf.d/default.conf
# 复制自定义配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# 复制静态文件
COPY html/ /usr/share/nginx/html/
# 创建 nginx 用户
RUN addgroup -g 1000 nginx && \
adduser -D -u 1000 -G nginx nginx
# 创建必要的目录并设置权限
RUN mkdir -p /var/cache/nginx /var/log/nginx && \
chown -R nginx:nginx /var/cache/nginx /var/log/nginx && \
chown -R nginx:nginx /usr/share/nginx/html
USER nginx
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]