Appearance
镜像、容器与 Dockerfile
这篇笔记聚焦 Docker 最核心的一条主线:
镜像是什么容器是什么Dockerfile在构建链路里做什么- 为什么项目里总在强调镜像优化和多阶段构建
如果这条主线没有理解清楚,后面再看网络、数据卷、编排,都会变成零散知识点。
1. 镜像到底是什么
镜像 可以理解成 一个用于启动容器的只读模板。
它里面通常会包含:
- 基础运行环境
- 应用代码或构建产物
- 依赖包
- 环境变量基础配置
- 启动命令
它解决的问题是 如何把应用运行所需的一切尽量标准化地打包出来。
这里要注意一个边界:
镜像 不等于“已经运行的应用”,
它更像是“运行前的标准化产物”。
2. 容器到底是什么
容器 可以理解成 镜像运行起来之后形成的实例。
实际写项目时,更多是这样:
- 镜像是静态的
- 容器是动态运行中的
- 一个镜像可以创建多个容器
例如:
- 你有一个
my-app:1.0镜像 - 可以基于它启动 3 个容器实例
- 它们运行同一份应用,但彼此是不同的运行单元
3. 镜像和容器到底有什么区别
| 对比项 | 镜像 | 容器 |
|---|---|---|
| 状态 | 静态 | 动态 |
| 是否运行中 | 否 | 是 |
| 作用 | 提供启动模板 | 提供运行实例 |
| 是否可多开 | 同一个镜像可启动多个容器 | 每个容器是独立实例 |
把这个区别记住:镜像像安装包或模板,容器像安装后真正跑起来的程序实例。
4. Dockerfile 是什么
Dockerfile 可以理解成 一份告诉 Docker 应该如何一步步构建镜像的说明文件。
它解决的是 镜像构建如何标准化、可重复、可自动化。
如果没有 Dockerfile,构建镜像就很容易退化成:
- 手工拷文件
- 手工装依赖
- 手工记启动命令
这显然不利于团队协作和 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 表示:在构建镜像时执行一条命令。
它常用于:
- 安装依赖
- 编译项目
- 做镜像内的准备工作
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"]这段配置表达的是:
- 以
node:20-alpine为基础 - 在
/app目录下工作 - 先复制依赖声明文件
- 安装依赖
- 再复制项目代码
- 执行构建
- 暴露应用端口
- 设置容器启动命令
7. 为什么总在强调镜像优化
镜像不是“只要能构建成功就行”。
镜像过大通常会带来这些问题:
- 构建更慢
- 推送和拉取更慢
- 存储成本更高
- 安全面暴露更大
所以项目里很常强调:
- 使用更小的基础镜像
- 减少无关文件进入镜像
- 利用缓存优化依赖安装
- 使用多阶段构建
8. 多阶段构建到底在解决什么问题
多阶段构建 可以理解成 把“编译环境”和“运行环境”拆开,最终镜像只保留真正运行需要的内容。
它解决的是:
- 最终镜像过大
- 构建工具链不应该被带进生产镜像
- 安全面过大
例如:
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这段配置的含义是:
- 第一阶段用 Node 环境构建前端产物
- 第二阶段只拿构建结果
- 最终运行镜像不再包含 Node 构建工具链
9. 工程上最常见的几个误区
9.1 误区一:把整个项目目录全部 COPY 进去
这样很容易把:
- 无关文件
- 本地缓存
- 日志
- 甚至敏感文件
一起打进镜像。
9.2 误区二:依赖和代码一起复制,导致缓存失效
如果每次代码变动都重新安装依赖,构建会慢很多。
9.3 误区三:把编译环境也带到最终镜像里
这通常会让镜像又大又重,还增加不必要的安全暴露面。
10. 一句话总结
镜像、容器和 Dockerfile 这一条主线,本质上是在解决:
应用如何被标准化打包、如何被一致地运行,以及如何把构建产物变成一个真正可交付的运行单元。