Docker 学习笔记(一):为什么需要镜像、容器和仓库?
我以前对 Docker 的理解很简单:
Docker 好像就是一个"装环境"的工具。
看完 Docker 入门视频之后,我发现这个理解不算错,但太粗糙了。
Docker 真正解决的问题不是"怎么安装 Node、MongoDB、Nginx",而是:
如何把一个应用运行所需的环境,打包成一份可复制、可分发、可复现的东西。
这篇文章先不急着堆命令,先把几个最容易混在一起的概念讲清楚:镜像、容器、Docker Hub、镜像仓库。
1. 问题从哪里来?
假设我有一个后端项目,依赖这些东西:
- Node.js
- MongoDB
- pnpm / npm
- 一堆环境变量
- 指定端口
- 指定启动命令
在我自己的电脑上,这些东西都配好了,所以项目可以跑。
但是换一台电脑,就可能出现这些问题:
bash
node: command not found
mongo: command not found
端口被占用
环境变量没配置
版本不一致
依赖安装失败
这就是经典的:
在我电脑上明明是好的。
Docker 的价值,就是把"我的电脑环境"变成一个可以复制的运行单元。
2. 镜像:可以理解成"应用运行环境的快照"
镜像,英文叫 Image。
它不是正在运行的程序,而是一份静态模板。
你可以把它理解成:
text
镜像 = 操作系统基础层 + 语言运行时 + 项目代码 + 依赖 + 默认启动命令
比如:
bash
docker pull nginx:alpine
这条命令做的事情是:从远程镜像仓库下载一个 nginx:alpine 镜像到本地。
这个镜像里面已经包含了 Nginx 运行所需的环境。
但是注意:
镜像本身不会运行,它只是一个模板。
真正跑起来的是容器。
3. 容器:由镜像创建出来的运行实例
容器,英文叫 Container。
如果镜像是"类",容器就是"对象"。
如果镜像是"安装包",容器就是"运行中的应用"。
比如:
bash
docker run -d --name my-nginx -p 8080:80 nginx:alpine
这条命令的意思是:
- 使用
nginx:alpine镜像 - 创建并启动一个容器
- 容器名字叫
my-nginx - 后台运行
- 把宿主机的
8080端口映射到容器的80端口
运行后访问:
text
http://localhost:8080
就能看到 Nginx 页面。
这个时候,本机并没有真的安装一个传统意义上的 Nginx,而是 Docker 在容器里帮我们运行了它。
4. 镜像和容器的关系
最容易混淆的是这句话:
镜像不是容器,容器也不是镜像。
它们的关系可以这样看:
text
Dockerfile --build--> 镜像 --run--> 容器
或者:
text
菜谱 --做菜--> 菜品模板 --端上桌--> 一份真正的菜
Dockerfile --构建--> 镜像 --运行--> 容器
你可以用同一个镜像创建多个容器:
bash
docker run -d --name nginx-1 -p 8081:80 nginx:alpine
docker run -d --name nginx-2 -p 8082:80 nginx:alpine
docker run -d --name nginx-3 -p 8083:80 nginx:alpine
这三个容器都来自同一个镜像,但它们是三个独立的运行实例。
5. Docker Hub:公共镜像仓库
我们平时执行:
bash
docker pull mongo:7
Docker 默认会去 Docker Hub 找 mongo:7 这个镜像。
你可以把 Docker Hub 理解成 Docker 世界里的 npm:
text
npm registry 存 npm 包
Docker Hub 存 Docker 镜像
常见镜像:
bash
docker pull nginx:alpine
docker pull mongo:7
docker pull redis:7
docker pull node:22-alpine
这些镜像别人已经做好了,我们可以直接使用。
6. 镜像仓库:不一定只有 Docker Hub
Docker Hub 是最常见的公共仓库,但不是唯一选择。
实际公司里还可能使用:
- Docker Hub 私有仓库
- 阿里云容器镜像服务
- 腾讯云镜像仓库
- 华为云 SWR
- Harbor 私有仓库
- 公司内网自建镜像仓库
也就是说,镜像仓库只是一个概念:
它负责保存、分发镜像。
Docker Hub 是其中一种实现。
7. 为什么公司内网经常拉不到镜像?
如果公司网络不能直接访问 Docker Hub,就会出现类似:
bash
failed to resolve reference "docker.io/library/mongo:7"
failed to fetch oauth token
connect timeout
本质原因不是 Docker 命令错了,而是:
Docker 客户端需要访问远程镜像仓库,但公司内网不允许,或者代理没有配置好。
解决方式通常有几种:
- 配置 Docker 代理。
- 使用公司内网镜像仓库。
- 在外网机器提前
docker pull,再docker save导出成 tar 包,拷贝到内网机器docker load。 - 由公司统一维护基础镜像。
比如离线导出:
bash
# 外网电脑
docker pull mongo:7
docker save -o mongo-7.tar mongo:7
# 内网电脑
docker load -i mongo-7.tar
这个思路非常适合不能直接访问 Docker Hub 的环境。
8. 一张图理解 Docker 的主线
text
编写 Dockerfile
│
▼
docker build
│
▼
生成镜像 image
│
┌───────┴────────┐
▼ ▼
docker run docker push
│ │
▼ ▼
启动容器 上传镜像仓库
│
▼
其他机器 docker pull
│
▼
docker run
这就是 Docker 的核心闭环:
写 Dockerfile → 构建镜像 → 运行容器 → 推送仓库 → 其他机器拉取运行。
9. 第一篇小结
这篇文章只讲心智模型。
几个概念可以这样记:
| 概念 | 作用 | 类比 |
|---|---|---|
| Dockerfile | 描述如何构建镜像 | 菜谱 |
| 镜像 Image | 静态运行环境模板 | 安装包 / 模板 |
| 容器 Container | 镜像运行后的实例 | 正在运行的程序 |
| Docker Hub | 公共镜像仓库 | npm registry |
| 私有镜像仓库 | 公司内部镜像分发中心 | 公司私有 npm 源 |
下一篇开始进入命令:docker run 后面那些 -p、-v、-e、--name、-d 到底都在控制什么。
参考资料
- Docker Docs: docs.docker.com/
- Docker Hub quickstart: docs.docker.com/docker-hub/...
- Build and push your first image: docs.docker.com/get-started...