Docker 学习笔记(一):为什么需要镜像、容器和仓库?

0 阅读5分钟

Docker 学习笔记(一):为什么需要镜像、容器和仓库?

我以前对 Docker 的理解很简单:

Docker 好像就是一个“装环境”的工具。

看完 Docker 入门视频之后,我发现这个理解不算错,但太粗糙了。

Docker 真正解决的问题不是“怎么安装 Node、MongoDB、Nginx”,而是:

如何把一个应用运行所需的环境,打包成一份可复制、可分发、可复现的东西。

这篇文章先不急着堆命令,先把几个最容易混在一起的概念讲清楚:镜像、容器、Docker Hub、镜像仓库


1. 问题从哪里来?

假设我有一个后端项目,依赖这些东西:

  • Node.js
  • MongoDB
  • pnpm / npm
  • 一堆环境变量
  • 指定端口
  • 指定启动命令

在我自己的电脑上,这些东西都配好了,所以项目可以跑。

但是换一台电脑,就可能出现这些问题:

node: command not found
mongo: command not found
端口被占用
环境变量没配置
版本不一致
依赖安装失败

这就是经典的:

在我电脑上明明是好的。

Docker 的价值,就是把“我的电脑环境”变成一个可以复制的运行单元。


2. 镜像:可以理解成“应用运行环境的快照”

镜像,英文叫 Image。

它不是正在运行的程序,而是一份静态模板

你可以把它理解成:

镜像 = 操作系统基础层 + 语言运行时 + 项目代码 + 依赖 + 默认启动命令

比如:

docker pull nginx:alpine

这条命令做的事情是:从远程镜像仓库下载一个 nginx:alpine 镜像到本地。

这个镜像里面已经包含了 Nginx 运行所需的环境。

但是注意:

镜像本身不会运行,它只是一个模板。

真正跑起来的是容器。


3. 容器:由镜像创建出来的运行实例

容器,英文叫 Container。

如果镜像是“类”,容器就是“对象”。

如果镜像是“安装包”,容器就是“运行中的应用”。

比如:

docker run -d --name my-nginx -p 8080:80 nginx:alpine

这条命令的意思是:

  • 使用 nginx:alpine 镜像
  • 创建并启动一个容器
  • 容器名字叫 my-nginx
  • 后台运行
  • 把宿主机的 8080 端口映射到容器的 80 端口

运行后访问:

http://localhost:8080

就能看到 Nginx 页面。

这个时候,本机并没有真的安装一个传统意义上的 Nginx,而是 Docker 在容器里帮我们运行了它。


4. 镜像和容器的关系

最容易混淆的是这句话:

镜像不是容器,容器也不是镜像。

它们的关系可以这样看:

Dockerfile  --build-->  镜像  --run-->  容器

或者:

菜谱       --做菜-->   菜品模板   --端上桌-->  一份真正的菜
Dockerfile --构建-->   镜像       --运行-->    容器

你可以用同一个镜像创建多个容器:

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:公共镜像仓库

我们平时执行:

docker pull mongo:7

Docker 默认会去 Docker Hub 找 mongo:7 这个镜像。

你可以把 Docker Hub 理解成 Docker 世界里的 npm:

npm registry  存 npm 包
Docker Hub    存 Docker 镜像

常见镜像:

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,就会出现类似:

failed to resolve reference "docker.io/library/mongo:7"
failed to fetch oauth token
connect timeout

本质原因不是 Docker 命令错了,而是:

Docker 客户端需要访问远程镜像仓库,但公司内网不允许,或者代理没有配置好。

解决方式通常有几种:

  1. 配置 Docker 代理。
  2. 使用公司内网镜像仓库。
  3. 在外网机器提前 docker pull,再 docker save 导出成 tar 包,拷贝到内网机器 docker load
  4. 由公司统一维护基础镜像。

比如离线导出:

# 外网电脑
docker pull mongo:7
docker save -o mongo-7.tar mongo:7

# 内网电脑
docker load -i mongo-7.tar

这个思路非常适合不能直接访问 Docker Hub 的环境。


8. 一张图理解 Docker 的主线

        编写 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 到底都在控制什么。


参考资料