Skip to content

镜像、容器与 Dockerfile

这篇笔记聚焦 Docker 最核心的一条主线:

  1. 镜像 是什么
  2. 容器 是什么
  3. Dockerfile 在构建链路里做什么
  4. 为什么项目里总在强调镜像优化和多阶段构建

如果这条主线没有理解清楚,后面再看网络、数据卷、编排,都会变成零散知识点。


1. 镜像到底是什么

镜像 可以理解成 一个用于启动容器的只读模板

它里面通常会包含:

  1. 基础运行环境
  2. 应用代码或构建产物
  3. 依赖包
  4. 环境变量基础配置
  5. 启动命令

它解决的问题是 如何把应用运行所需的一切尽量标准化地打包出来

这里要注意一个边界:

镜像 不等于“已经运行的应用”,
它更像是“运行前的标准化产物”。


2. 容器到底是什么

容器 可以理解成 镜像运行起来之后形成的实例

实际写项目时,更多是这样:

  1. 镜像是静态的
  2. 容器是动态运行中的
  3. 一个镜像可以创建多个容器

例如:

  1. 你有一个 my-app:1.0 镜像
  2. 可以基于它启动 3 个容器实例
  3. 它们运行同一份应用,但彼此是不同的运行单元

3. 镜像和容器到底有什么区别

对比项镜像容器
状态静态动态
是否运行中
作用提供启动模板提供运行实例
是否可多开同一个镜像可启动多个容器每个容器是独立实例

把这个区别记住:镜像像安装包或模板,容器像安装后真正跑起来的程序实例。


4. Dockerfile 是什么

Dockerfile 可以理解成 一份告诉 Docker 应该如何一步步构建镜像的说明文件

它解决的是 镜像构建如何标准化、可重复、可自动化

如果没有 Dockerfile,构建镜像就很容易退化成:

  1. 手工拷文件
  2. 手工装依赖
  3. 手工记启动命令

这显然不利于团队协作和 CI/CD。


5. Dockerfile 里的常见指令是什么意思

5.1 FROM

FROM 表示:当前镜像基于哪个基础镜像开始构建。

例如:

dockerfile
FROM node:20-alpine

这里的 alpine 指的是一种更精简的 Linux 发行版镜像,常用来减小基础镜像体积。

5.2 WORKDIR

WORKDIR 表示:后续命令执行时所在的工作目录。

5.3 COPY

COPY 表示:把构建上下文中的文件复制进镜像。

这里的 构建上下文 可以理解成 docker build 命令提交给 Docker 引擎作为构建输入的那一批文件

5.4 RUN

RUN 表示:在构建镜像时执行一条命令。

它常用于:

  1. 安装依赖
  2. 编译项目
  3. 做镜像内的准备工作

5.5 CMD

CMD 可以理解成 容器启动时默认执行的命令

它更像默认值,运行容器时可以被覆盖。

5.6 ENTRYPOINT

ENTRYPOINT 可以理解成 容器启动时相对固定的入口命令

它和 CMD 的区别在于:

ENTRYPOINT 更像“主程序入口”,而 CMD 更像“默认参数或默认命令”。


6. 一个典型的 Dockerfile 长什么样

dockerfile
FROM node:20-alpine

WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build

EXPOSE 3000

CMD ["npm", "run", "start"]

这段配置表达的是:

  1. node:20-alpine 为基础
  2. /app 目录下工作
  3. 先复制依赖声明文件
  4. 安装依赖
  5. 再复制项目代码
  6. 执行构建
  7. 暴露应用端口
  8. 设置容器启动命令

7. 为什么总在强调镜像优化

镜像不是“只要能构建成功就行”。

镜像过大通常会带来这些问题:

  1. 构建更慢
  2. 推送和拉取更慢
  3. 存储成本更高
  4. 安全面暴露更大

所以项目里很常强调:

  1. 使用更小的基础镜像
  2. 减少无关文件进入镜像
  3. 利用缓存优化依赖安装
  4. 使用多阶段构建

8. 多阶段构建到底在解决什么问题

多阶段构建 可以理解成 把“编译环境”和“运行环境”拆开,最终镜像只保留真正运行需要的内容

它解决的是:

  1. 最终镜像过大
  2. 构建工具链不应该被带进生产镜像
  3. 安全面过大

例如:

dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

这段配置的含义是:

  1. 第一阶段用 Node 环境构建前端产物
  2. 第二阶段只拿构建结果
  3. 最终运行镜像不再包含 Node 构建工具链

9. 工程上最常见的几个误区

9.1 误区一:把整个项目目录全部 COPY 进去

这样很容易把:

  1. 无关文件
  2. 本地缓存
  3. 日志
  4. 甚至敏感文件

一起打进镜像。

9.2 误区二:依赖和代码一起复制,导致缓存失效

如果每次代码变动都重新安装依赖,构建会慢很多。

9.3 误区三:把编译环境也带到最终镜像里

这通常会让镜像又大又重,还增加不必要的安全暴露面。


10. 一句话总结

镜像、容器和 Dockerfile 这一条主线,本质上是在解决:

应用如何被标准化打包、如何被一致地运行,以及如何把构建产物变成一个真正可交付的运行单元。

基于 VitePress 构建的个人技术笔记。