Docker 容器是一种轻量级、可移植、自给自足的软件运行环境。其核心思想是将应用程序及其所有依赖(包括代码、运行时、系统工具、系统库和配置文件等)打包封装在一个标准化的容器镜像中。 这一封装确保了应用无论运行在哪台已安装 Docker 的主机上,都能获得一致的运行效果,极大地消除了环境差异带来的问题。
容器通过操作系统级虚拟化,提供进程级隔离,并共享主机内核,从而实现高性能、低资源开销和极快的启动速度。Docker 容器具备高度的便携性、弹性伸缩和易于分发的特性,已成为现代云原生和 DevOps 流程中的基础组件。 这节课我们将深入探讨 Docker 容器的工作机制及其在实际开发与运维中的应用价值。

为了理解容器的精妙之处,我们得先认识一下它的“前辈”——虚拟机(VM)。
假设开发者小明接到了一个任务:他需要在一台物理服务器上同时运行 4 个独立的应用程序。 在过去,他会使用虚拟机技术。这就像是,为了让 4 个家庭(应用程序)住下,他在一块土地(物理服务器)上盖了 4栋独立的别墅(虚拟机)。每栋别墅都有自己完整的配套设施:地基、水管、电路、屋顶,一应俱全。然后,每个家庭才能入住。
这个模式看起来很完美,但问题也随之而来。每栋别墅都需要一整套独立的设施,这造成了巨大的资源浪费。我们称之为“虚拟机税”——你为操作系统本身付出的额外开销。4 栋别墅意味着 4 套独立的操作系统、4份资源消耗,管理起来也费时费力。
现在,我们来看看容器是怎么做的。容器技术就像是在同一块土地上,盖了一栋高层公寓楼。这栋楼共享同一个地基和主体结构(主机的操作系统)。然后,再把大楼分割成一个个独立的公寓套间(容器),分给不同的家庭(应用程序)居住。 每个套间都设施齐全,拎包入住,但它们共享了公寓楼的基础设施。这样一来,资源利用率大大提高,启动速度飞快(因为不用从打地基开始),而且管理也变得异常轻松。
下面这张图可以让你更直观地理解它们的区别:
传统虚拟机模型:
Docker容器模型:
总而言之,虚拟机虚拟化的是硬件,造出来的是一个个“重量级”的完整电脑;而容器虚拟化的是操作系统,变出来的是一个个“轻量级”的独立应用空间。这种轻巧、高效的特性,正是 Docker 容器如此受欢迎的关键原因。
理论知识已经储备完毕,现在是时候动手实践了!让我们一起创建并“驯养”你的第一个 Docker 容器。
首先,请确保你的电脑上已经安装好了 Docker。你可以通过在终端(命令行工具)里输入 docker version 来检查。如果能看到 Client 和 Server 的版本信息,那就说明一切就绪。如果没有,请返回到目录查看Docker的安装指南部分。
准备好了吗?在你的终端里输入下面这行命令,然后按下回车:
|$ docker run -it ubuntu /bin/bash
这行命令做了什么呢?让我们把它拆解开来看:
docker run: 这是最核心的命令,告诉 Docker:“嗨,我要启动一个新容器!”-it: 这是两个参数的缩写。-i 让我们能和容器进行交互,-t 则为这个交互分配一个终端。合在一起,就是“我要和这个容器进行一次亲密的实时对话”。ubuntu: 这告诉 Docker 使用哪个镜像来创建容器。镜像是容器的“模板”,我们这里用的是广受欢迎的 Ubuntu Linux 操作系统镜像。如果本地没有这个镜像,Docker 会很智能地自动从网上下载。/bin/bash: 这是我们希望在容器启动后运行的程序。在这里,我们启动了一个 Bash Shell,也就是一个命令行的交互界面。按下回车后,你会发现你的命令行提示符变了,类似 root@xxxxxxx:/#。恭喜你!你已经成功进入了容器的内部世界!现在你输入的任何命令,都是在这个隔离的 Ubuntu 环境中执行的。
把容器想象成一只电子宠物。它有自己的生命周期,你可以控制它的“苏醒”与“沉睡”。
当你在这个容器的命令行里输入 exit 并回车,你就结束了 /bin/bash 这个主程序。由于容器的主程序一旦结束,容器自身也就完成了使命,它会自动停止并退出。你的“宠物”睡着了。
但是,如果你想暂时离开,又不想让它“睡着”怎么办呢?
在容器的终端里,按住 Ctrl 键,然后依次按下 P 和 Q 键。这个神奇的组合键可以让你安全地“分离”(detach)出容器,回到你自己的电脑终端,而容器本身会继续在后台运行。你的“宠物”在你离开后,依旧保持着活力!
你可以使用 docker ps 命令来查看当前正在后台活蹦乱跳的容器。
那如果想重新连接到那个在后台运行的容器,怎么办?你需要使用 docker exec 命令,它就像是再次打开了宠物小屋的门。
当你的“宠物”睡着了(容器停止了),你可以用 docker start <容器名字或ID> 来唤醒它。如果你觉得不再需要它了,可以先用 docker stop <容器名字或ID> 让它优雅地停下来,然后用 docker rm <容器名字或ID> 把它彻底删除。
这就是容器最基础的生命周期管理,是不是很简单?
有时候,容器里运行的程序可能会因为意外而出错,导致容器停止。我们当然不希望服务就此中断。Docker 提供了一个很棒的“自愈”机制,叫做重启策略。
这就像给你的容器一个“不倒翁”的属性。无论怎么被推倒,它都会自己尝试着重新站起来。最常用的策略是 always(总是重启)和 unless-stopped(除非手动停止,否则总是重启)。
你可以在 docker run 的时候,加上 --restart 参数来指定策略,例如 --restart always。这样,一旦容器意外挂掉,Docker 就会立刻自动把它重新拉起,保证了服务的持续性。
光在命令行里玩还不够酷,让我们来用容器部署一个真正的网站! 我们会启动一个内置了网页服务器的容器。输入以下命令:
|$ docker run -d -p 80:8080 --name webserver nigelpoulton/ddd-book:web0.1
这个命令有点新东西:
-d: 代表“detached”,意思是让容器在后台运行。这样你就不会被卡在容器的终端里,可以继续在自己的电脑上做别的事情。-p 80:8080: 这是关键的一步,叫做“端口映射”。它像一个酒店的总机服务员。所有打到酒店总机(主机电脑的 80 端口)的电话,都会被转接到容器内部的 8080 分机(程序监听的端口)。这样,外部世界就能访问到容器里运行的网站服务了。--name webserver: 我们给这个容器取了个好记的名字,叫 webserver。命令执行后,打开你的浏览器,访问 http://localhost。如果一切顺利,你将看到一个欢迎页面。这个网页,就是由你刚刚启动的那个 Docker 容器提供服务的!
我们已经学了不少命令,这里为你整理成一个速查小词典,方便你随时回顾: