Docker build 命令(实战指南)

Docker build 命令:从零开始构建你的第一个镜像

在现代软件开发中,Docker 已经成为不可或缺的工具。它让“在本地运行没问题,上线就崩”的问题变得越来越少。而要使用 Docker,最关键的一步就是构建镜像——这正是 Docker build 命令的职责所在。

想象一下,你正在制作一道复杂的菜肴。你有食材(代码)、食谱(Dockerfile)、炉灶(Docker 引擎)。Docker build 命令就是那个“开始烹饪”的指令。它读取你的 Dockerfile,按照步骤一步步把代码“煮熟”,最终生成一个可以分发、部署的完整镜像。

对于初学者来说,Docker build 命令可能看起来有些神秘,但只要掌握了它的基本用法和底层逻辑,你会发现它其实非常直观。


什么是 Docker build 命令?

Docker build 命令是 Docker CLI 中用于构建镜像的核心命令。它的作用是:根据 Dockerfile 中的指令,创建一个可重复、可移植的镜像文件

简单来说,你写好 Dockerfile,然后运行 docker build,Docker 就会从头开始执行里面的所有指令,把你的应用打包成一个镜像。这个镜像可以被保存、分享、运行在任何支持 Docker 的机器上。

💡 关键点:Dockerfile 是构建的“说明书”,Docker build 是执行说明书的“厨师”。


基础语法与常用选项

Docker build 命令的基本语法如下:

docker build [选项] <上下文路径>

这里的“上下文路径”指的是构建时 Docker 所能看到的文件范围。它不一定是当前目录,但通常是项目根目录。

常用选项说明

选项 作用 示例
-t 为镜像指定名称和标签 docker build -t myapp:1.0 .
-f 指定 Dockerfile 文件名(非默认文件) docker build -f Dockerfile.prod .
--build-arg 传入构建时变量 docker build --build-arg ENV=prod .
--no-cache 强制不使用缓存,重新构建所有层 docker build --no-cache .
--progress 控制构建过程的输出进度 docker build --progress=plain .

这些选项让 Docker build 变得非常灵活,能适应不同场景。


创建一个简单的项目来实践

我们来创建一个最基础的 Node.js 应用,然后用 Docker build 构建镜像。

步骤 1:创建项目结构

在你的工作目录中创建如下结构:

my-node-app/
├── Dockerfile
├── package.json
└── app.js

步骤 2:编写 app.js

// app.js
// 这是一个简单的 Node.js 服务,监听 3000 端口
// 当访问根路径时,返回 "Hello from Docker!"
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello from Docker!');
});

// 启动服务,监听 3000 端口
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

步骤 3:编写 package.json

{
  "name": "my-node-app",
  "version": "1.0.0",
  "main": "app.js",
  "dependencies": {
    "express": "^4.18.2"
  },
  "scripts": {
    "start": "node app.js"
  }
}

步骤 4:编写 Dockerfile

FROM node:18-alpine

WORKDIR /app

COPY package.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

🔍 注释说明:

  • FROM 表示从哪个镜像开始构建,这里是 Node.js 官方镜像。
  • WORKDIR 设置容器内的工作目录,避免路径混乱。
  • COPY 用于将本地文件复制到容器中,注意顺序很重要(先复制依赖文件,再复制代码)。
  • RUN npm install 会在构建时执行安装,避免运行时再装包。
  • EXPOSE 只是声明端口,不实际开放。
  • CMD 定义容器启动后默认运行的命令。

执行 Docker build 命令

现在,进入 my-node-app 目录,运行以下命令:

docker build -t myapp:1.0 .
  • -t myapp:1.0:为镜像命名并打上标签。myapp 是名称,1.0 是版本标签。
  • .:表示当前目录为构建上下文。

执行后你会看到类似输出:

Sending build context to Docker daemon  3.072kB
Step 1/7 : FROM node:18-alpine
 ---> 9d6b6b49c38e
Step 2/7 : WORKDIR /app
 ---> Running in 5f6a7b8c9d0e
Removing intermediate container 5f6a7b8c9d0e
 ---> 8c9d0e1f2a3b
...
Successfully built 8c9d0e1f2a3b
Successfully tagged myapp:1.0

✅ 成功!Docker 已经根据 Dockerfile 构建出一个名为 myapp:1.0 的镜像。


镜像构建过程详解:分层构建机制

Docker build 的强大之处在于它的“分层构建”机制。每一行 Dockerfile 指令都会生成一个独立的层(layer),Docker 会缓存这些层。

为什么分层很重要?

想象你正在搭积木。如果你每次修改代码都要重新搭整座城堡,那效率极低。但如果你只换掉顶层积木,下面的可以复用,那就会快很多。

Docker build 的缓存机制就是这个道理:

  • 第一次构建:所有层都重新创建。
  • 第二次构建(仅修改了 app.js):COPY . . 这一步会因为文件内容变化而重新执行,但 RUN npm install 会复用缓存(因为 package.json 没变)。
  • 第三次构建(只改了注释):如果 Dockerfile 本身没变,且上下文文件没变,整个构建过程可能直接从缓存中恢复。

⚠️ 注意:Docker 会比较 COPYADD 指令中的文件内容,如果内容没变,就使用缓存。

如何验证缓存?

运行以下命令查看镜像列表:

docker images

你应该能看到:

REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
myapp        1.0       8c9d0e1f2a3b   2 minutes ago   115MB

这个 8c9d0e1f2a3b 就是你刚刚构建的镜像 ID。


高级用法:使用构建参数与多阶段构建

使用构建参数(Build Args)

有时你需要在构建时传入变量,比如环境变量。

修改 Dockerfile:

ARG NODE_ENV=development

ENV NODE_ENV=$NODE_ENV

FROM node:18-alpine
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

构建时传入参数:

docker build --build-arg NODE_ENV=production -t myapp:prod .

这样,镜像构建时就会使用 production 模式,适合生产环境。


多阶段构建(Multi-stage Build)

如果你的应用需要编译(如 Vue、React、Go、Java),可以使用多阶段构建来减小最终镜像体积。

例如,一个 React 项目:

FROM node:18-alpine AS builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

📌 这样做,最终镜像只包含 nginx 和打包后的静态文件,体积从几百 MB 降到几十 MB。


常见问题与解决方案

问题 原因 解决方法
构建失败,提示 COPY failed: stat /...: no such file or directory 文件路径错误或上下文未包含文件 检查 Dockerfile 路径是否正确,确保文件在上下文目录中
构建速度慢 缓存未命中或网络问题 使用 --no-cache 排查,或检查 COPY 是否频繁变动
镜像过大 未清理临时文件或使用了大基础镜像 使用多阶段构建,删除不必要的依赖包
无法访问端口 没有正确暴露端口或启动命令错误 检查 EXPOSECMD 是否正确

总结:掌握 Docker build 命令,开启容器化之旅

Docker build 命令 是你进入容器化世界的第一步。它不只是一个命令,更是一种“将代码变成可运行、可分发的标准化产物”的思维方式。

通过本篇教程,你已经学会了:

  • 如何编写基本的 Dockerfile
  • 如何使用 docker build 构建镜像
  • 理解分层构建与缓存机制
  • 掌握常用选项与高级技巧(构建参数、多阶段构建)

记住:每一次 docker build 的成功,都意味着你的应用离“一次构建,处处运行”更近了一步。

别再担心“我本地运行没问题,服务器却报错”了。只要用好 Docker build,你的代码,就能在任何地方稳定运行。

现在,打开你的项目,试试构建一个属于你的镜像吧!