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

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 客户端需要访问远程镜像仓库,但公司内网不允许,或者代理没有配置好。

解决方式通常有几种:

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

比如离线导出:

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


参考资料

相关推荐
lpfasd1232 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse4564 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai4 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记5 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁5 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu5 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!6 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格6 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人6 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid6 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet