Docker build创建镜像命令入门教程

一、核心概念
  1. Dockerfile

    定义镜像构建步骤的文本文件,包含一系列指令和配置,用于自动化创建镜像。

  2. 镜像层(Layer)

    Docker 镜像由多层只读层叠加而成,每个指令(如 RUNCOPY)会生成一个新的层。层可缓存,加速重复构建。

  3. 构建上下文(Build Context)

    发送给 Docker 守护进程的文件集合,用于构建镜像。默认是 Dockerfile 所在目录。

二、Dockerfile 基础指令

1. FROM

  • 用途 :指定基础镜像,所有 Dockerfile 必须以 FROM 开头。

  • 示例

    dockerfile 复制代码
    FROM nginx:latest  # 基于官方 Nginx 镜像

2. RUN

  • 用途:执行 shell 命令,生成新的镜像层。

  • 示例

    dockerfile 复制代码
    RUN apt-get update && apt-get install -y curl  # 安装依赖

3. COPY

  • 用途:将本地文件或目录复制到镜像中。

  • 示例

    dockerfile 复制代码
    COPY ./src /app/src  # 复制宿主机的 src 目录到镜像的 /app/src

4. ADD

  • 用途 :类似 COPY,但支持自动解压压缩文件(如 .tar.gz)和远程 URL。

  • 示例

    dockerfile 复制代码
    ADD https://example.com/file.tar.gz /app/  # 下载并解压文件

5. WORKDIR

  • 用途 :设置工作目录,后续指令(如 RUNCOPY)将在此目录执行。

  • 示例

    dockerfile 复制代码
    WORKDIR /app  # 切换到 /app 目录

6. CMD

  • 用途:定义容器启动时默认执行的命令(可被覆盖)。

  • 示例

    dockerfile 复制代码
    CMD ["node", "server.js"]  # 启动 Node.js 服务

7. ENTRYPOINT

  • 用途 :定义容器启动时执行的命令(不可被覆盖,但可通过 --entrypoint 修改)。

  • 示例

    dockerfile 复制代码
    ENTRYPOINT ["python", "app.py"]  # 固定执行 Python 脚本

8. EXPOSE

  • 用途 :声明容器监听的端口(仅文档作用,实际需通过 -p 映射)。

  • 示例

    dockerfile 复制代码
    EXPOSE 8080  # 声明应用使用 8080 端口

9. ENV

  • 用途:设置环境变量。

  • 示例

    dockerfile 复制代码
    ENV API_URL=https://api.example.com  # 定义 API 地址
三、docker build 命令详解

基本语法

bash 复制代码
docker build [OPTIONS] PATH | URL | -

常用选项

  • -t, --tag:指定镜像名称和标签(格式:name:tag)。
  • -f, --file:指定 Dockerfile 路径(默认为 PATH/Dockerfile)。
  • --no-cache:禁用缓存,强制重新执行所有步骤。
  • --build-arg:传递构建参数(需在 Dockerfile 中用 ARG 定义)。

示例

  1. 构建并标记镜像:

    bash 复制代码
    docker build -t my_app:v1 .  # 当前目录为构建上下文
  2. 指定 Dockerfile 路径:

    bash 复制代码
    docker build -t my_app:v1 -f Dockerfile.prod .
  3. 传递构建参数:

    bash 复制代码
    docker build --build-arg ENV=prod -t my_app:prod .
四、构建流程示例

目标:构建一个 Node.js 应用镜像。

步骤 1:创建项目结构

bash 复制代码
mkdir -p node-app/{src,public}
touch node-app/server.js node-app/package.json

步骤 2:编写 Dockerfile

dockerfile 复制代码
# 使用官方 Node.js 18 镜像作为基础
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json
COPY package*.json ./

# 安装依赖
RUN npm install

# 复制应用源码
COPY . .

# 暴露端口 3000
EXPOSE 3000

# 启动应用
CMD ["node", "server.js"]

步骤 3:构建镜像

bash 复制代码
docker build -t node-app:latest .

步骤 4:运行容器

bash 复制代码
docker run -p 3000:3000 node-app:latest
五、最佳实践
  1. 减少镜像层数

    合并相关指令(如 RUN apt-get update && apt-get install -y ...),避免生成过多无用层。

  2. 使用 .dockerignore

    排除构建上下文中的无关文件(如 node_modules.git),减少传输大小。

    plaintext 复制代码
    .git
    node_modules
    *.log
  3. 多阶段构建(Multi-Stage Builds)

    分离构建环境和运行环境,减小最终镜像体积。

    dockerfile 复制代码
    # 阶段 1:构建应用
    FROM node:18 AS builder
    WORKDIR /app
    COPY . .
    RUN npm install && npm run build
    
    # 阶段 2:运行应用
    FROM node:18-alpine
    WORKDIR /app
    COPY --from=builder /app/dist ./dist
    CMD ["node", "dist/server.js"]
  4. 使用轻量级基础镜像

    优先选择 Alpine Linux 或 distroless 镜像,减少镜像体积和安全风险。

    dockerfile 复制代码
    FROM node:18-alpine  # 体积约 100MB,远小于默认的 Ubuntu 镜像
  5. 避免以 root 用户运行

    创建非 root 用户,提升容器安全性。

    dockerfile 复制代码
    RUN adduser -D app_user
    USER app_user
六、调试与优化
  1. 查看构建日志

    bash 复制代码
    docker build --progress=plain -t my_app:debug .  # 显示详细日志
  2. 跳过缓存

    bash 复制代码
    docker build --no-cache -t my_app:nocache .
  3. 分析镜像层

    bash 复制代码
    docker history my_app:latest  # 查看各层大小和命令
  4. 扫描镜像漏洞

    使用 docker scan 或第三方工具(如 Trivy)检查安全风险。

    bash 复制代码
    docker scan my_app:latest
七、常见问题
  1. 构建失败:文件未找到

    • 原因:COPYADD 指令路径错误。
    • 解决:检查文件是否在构建上下文中,使用绝对路径或正确相对路径。
  2. 权限拒绝(Permission Denied)

    • 原因:容器内进程以非 root 用户运行,但文件权限不足。
    • 解决:在 Dockerfile 中使用 RUN chown 修改文件所有者。
  3. 缓存未生效

    • 原因:构建上下文文件变更导致缓存失效。
    • 解决:尽量保持静态文件(如依赖包)不变,或合理拆分指令。
  4. 端口无法访问

    • 原因:未通过 -p 映射端口。
    • 解决:运行容器时添加 -p 主机端口:容器端口,如 docker run -p 8080:80 nginx
八、总结
  • Dockerfile 是镜像构建的核心,需合理设计指令顺序和层结构。
  • docker build 命令通过参数控制镜像名称、上下文和缓存策略。
  • 遵循最佳实践(如多阶段构建、轻量级镜像)可显著优化构建效率和安全性。