一、Docker简介:容器技术起源、Docker与虚拟机对比、核心概念

1.1 容器技术起源——从 chroot 到 Docker

聊 Docker 之前,得先说说容器这玩意儿打哪儿来的。我最早接触容器概念是在 2008 年,当时还在折腾 Linux VServer 和 OpenVZ,说白了就是操作系统级的虚拟化。但真正让容器火起来的,是 2013 年 Docker 的发布。

Docker 其实不是发明了容器,而是把容器技术包装成了一套好用的工具链。容器的基础是 Linux 内核的两个特性:

  • Namespaces(命名空间):隔离进程、网络、挂载点、用户等资源。
  • Cgroups(控制组):限制资源使用量,比如 CPU、内存、磁盘 IO。

嗯,这里要提一嘴 chroot。早在 1979 年 Unix V7 就有 chroot,它能把进程的根目录换成别的路径。但 chroot 不够安全,也没法做资源限制。直到 2008 年 LXC(Linux Containers)出现,才算有了现代容器的雏形。

Docker 正是在 LXC 基础上加上镜像层、Dockerfile、仓库等概念,让“构建一次,到处运行”成为现实。

一句话记住:容器 = Namespaces(隔离) + Cgroups(限制) + 分层镜像(可复用)。

1.2 Docker vs 虚拟机——别再问哪个更快

我经常被问:「Docker 和虚拟机到底选哪个?」其实它们不是替代关系,而是不同场景的工具。下面这个表格,是我讲课必用的对比清单:

对比项 Docker 容器 传统虚拟机
操作系统 共享宿主机内核 每个 VM 有独立 Guest OS
启动速度 毫秒级(秒内启动) 分钟级(加载完整 OS)
资源占用 轻量,只有进程+文件系统 重量,需分配固定内存/磁盘
隔离程度 进程级隔离 硬件级虚拟化(更安全)
镜像大小 通常几十 MB 到几百 MB 几 GB 起步
适用场景 微服务、CI/CD、开发环境 传统应用、多 OS 共存

我自己在项目中踩过坑:有一次给客户部署 Java 应用,对方坚持用虚拟机,结果十几台 ESXi 主机硬生生跑了 200 多个 VM,管理起来简直噩梦。换成 Docker 后,同样资源能跑 500 多个容器,运维成本直线下降。当然,如果你是跑 Windows 应用或者需要强隔离的场景,那还是乖乖用虚拟机吧。

我的经验:开发环境、CI/CD、微服务首选 Docker;数据库、Windows 应用、多租户强隔离场景用虚拟机。

1.3 三个核心概念——镜像、容器、仓库

这三个概念别说你背过,要真的理解它们之间的关系。我画个图帮你理清:

Docker 核心概念关系 Image 只读模板 Container 运行实例 Registry 存储分发 docker run docker pull docker push docker commit(不推荐) 理解要点: • 镜像(Image)是只读模板,好比一个 ZIP 包。 • 容器(Container)是镜像的运行实例,有读写层。 • 仓库(Registry)是集中存储和分发镜像的地方,类似 GitHub 但存的是 Docker 镜像。

详解三个概念

镜像(Image)

镜像是一个轻量的、可执行的独立软件包。它包含运行某软件所需的所有东西:代码、运行时、系统工具、系统库、设置。我习惯把镜像比作一个「预制菜包」——里面食材、调料、火候全配好了,拿到手直接加热就能吃。

Docker 镜像由多层组成,每一层代表一个 Dockerfile 指令。这种结构的好处是:

  • 共享缓存:基础层(如 Ubuntu)被多个镜像共用,本地只存一份。
  • 增量更新:改代码只改最上层,不用重新下载整个系统。

如果你执行过 docker images,应该见过类似输出:

REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    605c77e624dd   2 weeks ago    188MB
node          20-alpine 5c1c2c9b3c7a   3 weeks ago    127MB

容器(Container)

容器是镜像的运行实例。每个容器在镜像的只读层之上加一层读写层。你可以对容器做任何操作:读文件、改配置、装软件,但容器删除后这些改动就没了——除非你执行 docker commit 把它保存为新镜像。

嗯,这里要注意:我从来不建议在生产上用 docker commit 制作镜像。你想想看,那样做没法追踪变更,也没法复现。正确做法是用 Dockerfile 声明式构建。

启动一个容器很简单:

docker run -d --name my-web -p 8080:80 nginx:latest

这条命令做了什么?拉取 nginx:latest 镜像(如果本地没有),创建一个名为 my-web 的容器,把宿主机的 8080 端口映射到容器的 80 端口,然后在后台运行。

仓库(Registry)

仓库就是存镜像的地方。Docker 默认用的是 Docker Hub —— 公共的官方仓库。但很多企业会搭建私有仓库,比如 Harbor、GitLab Container Registry、AWS ECR。我在一家金融公司做项目时就遇到过,监管要求所有镜像不能外泄,于是自建了 Harbor,配合项目流水线做镜像扫描和签名,那才叫安全。

常用命令:

# 拉取镜像
docker pull ubuntu:22.04

# 推送镜像到自定义仓库
docker tag my-app:latest myregistry.com/team/my-app:1.0
docker push myregistry.com/team/my-app:1.0
我曾经踩过的坑:刚用 Docker 时直接在 Docker Hub 上公开 push 了包含数据库密码的镜像,结果被爬虫扫到,光速被人拉走。记住:镜像里永远不要硬编码密钥,用环境变量或 secret 管理。

小结一下

本章我们聊了容器技术的起源——从 chroot 到 LXC 再到 Docker 的进化。Docker 通过 Namespaces 和 Cgroups 实现轻量级隔离,和虚拟机最大的区别是共享宿主机内核,启动快、资源省。三个核心概念:镜像(只读模板)、容器(运行实例)、仓库(存储分发)。

在后面的课程中,我会手把手带你写 Dockerfile、做镜像版本锁定、做多阶段构建,还会讲怎么做镜像瘦身和 CI/CD 集成。别急,先把基础垒扎实。