第1章 容器生态系统
摘要 :本章全面介绍了容器技术生态系统,从容器技术的整体认知到具体实践。首先阐述了学习容器技术的重要性,然后系统性地讲解了容器生态系统的三个层次:核心技术 (容器规范、runtime、管理工具、定义工具、Registry、容器OS)、平台技术 (编排引擎、管理平台、基于容器的PaaS)和支持技术(网络、服务发现、监控、数据管理、日志管理、安全性)。最后通过详细的 CentOS Stream 8 环境下的 Docker 安装教程和 C/S 分离部署实践,帮助读者快速搭建实验环境并运行第一个容器,为后续深入学习打下坚实基础。
001 了解容器技术
1.系统讲解当前最流行的容器技术。 从容器的整个生态环境到各个具体的技术,从整体到细节逐一讨论。
2.重实践并兼顾理论。 从实际操作的角度带领大家学习容器技术。
为什么要学这个?
简单回答是:容器技术非常热门,但门槛高。
容器技术是继大数据和云计算之后又一炙手可热的技术,而且未来相当一段时间内都会非常流行。
对 IT 行业来说,这是一项非常有价值的技术。而对 IT 从业者来说,掌握容器技术是市场的需要,也是提 升自我价值的重要途径。
现在以 Docker 为代表的容器技术来了,而且关注度越来越高,这一点可以从 google 趋势 中 Docker 的 搜索上升趋势(蓝色曲线)中清楚看到。

002 容器生态系统
对于像容器这类平台级别的技术,通常涉及的知识范围会很广,相关的软件,解决方案也会很多,初学 者往往容易迷失。
那怎么办呢? 我们可以从生活经验中寻找答案。
当我们去陌生城市旅游想了解一下这个城市一般我们会怎么做?
我想大部分人应该会打开手机看一下这个城市的地图:
1.城市大概的位置和地理形状是什么?
2.都由哪几个区或县组成?
3.主要的交通干道是哪几条?
同样的道理,学习容器技术我们可以先从天上鸟瞰一下:
1.容器生态系统包含哪些不同层次的技术?
2.不同技术之间是什么关系?
3.哪些是核心技术哪些是辅助技术?
首先得对容器技术有个整体认识,之后我们的学习才能够有的放矢,才能够分清轻重缓急,做到心中有数,这样就不容易迷失了。
接下来我会根据自己的经验帮大家规划一条学习路线,一起探索容器生态系统。
学习新技术得到及时反馈是非常重要的,所以我们马上会搭建实验环境,并运行第一个容器,感受什么是容器。
千里之行始于足下,让我们从了解生态系统开始吧。
鸟瞰容器生态系统
一谈到容器,大家都会想到 Docker。
Docker 现在几乎是容器的代名词。确实,是 Docker 将容器技术发扬光大。同时,大家也需要知道围绕 Docker 还有一个生态系统。Docker 是这个生态系统的基石,但完善的生态系统才是保障 Docker 以及容器技术能够真正健康发展的决定因素。
大致来看,容器生态系统包含核心技术、平台技术和支持技术。

下面分别介绍。
容器核心技术
容器核心技术是指能够让 container 在 host os上运行起来的那些技术。

这些技术包括容器规范、容器 runtime、容器管理工具、容器定义工具、Registry 以及 容器 OS,下面分别介绍。
容器规范
容器不光是 Docker,还有其他容器,比如 CoreOS 的 rkt、红帽公司podman、containerd。为了保证容器生态的健康发展,保证不同容器之间能够兼容,包含 Docker、CoreOS、Google在内的若干公司共同成立了一个叫 Open Container Initiative(OCI) 的组织,其目是制定开放的容器规范。

目前 OCI 发布了两个规范:runtime spec 和 image format spec。
有了这两个规范,不同组织和厂商开发的容器能够在不同的 runtime 上运行。这样就保证了容器的可移植性和互操作性。
容器 runtime
runtime 是容器真正运行的地方。runtime 需要跟操作系统 kernel 紧密协作,为容器提供运行环境。
如果大家用过 Java,可以这样来理解 runtime 与容器的关系:
Java 程序就好比是容器,JVM 则好比是 runtime。JVM 为 Java 程序提供运行环境。同样的道理,容器只有在 runtime 中才能运行。

lxc、runc 和 rkt 是目前主流的三种容器 runtime。
lxc 是 Linux 上老牌的容器 runtime。Docker 最初也是用 lxc 作为 runtime。
runc 是 Docker 自己开发的容器 runtime,符合 oci 规范,也是现在 Docker 的默认 runtime。
rkt 是 CoreOS 开发的容器 runtime,符合 oci 规范,因而能够运行 Docker 的容器。
容器管理工具
光有 runtime 还不够,用户得有工具来管理容器啊。容器管理工具对内与 runtime 交互,对外为用户提供 interface,比如 CLI。这就好比除了 JVM,还得提供 java 命令让用户能够启停应用不是。

lxd 是 lxc 对应的管理工具。
runc 的管理工具是 docker engine。docker engine 包含后台 deamon 和 cli 两个部分。我们通常提到 Docker,一般就是指的 docker engine。
rkt 的管理工具是 rkt cli。
容器定义工具
容器定义工具允许用户定义容器的内容和属性,这样容器就能够被保存,共享和重建。

docker image 是 docker 容器的模板,runtime 依据 docker image 创建容器。
dockerfile 是包含若干命令的文本文件,可以通过这些命令创建出 docker image。
ACI (App Container Image) 与 docker image 类似,只不过它是由 CoreOS 开发的 rkt 容器的 image 格 式。
Registry
容器是通过 image 创建的,需要有一个仓库来统一存放 image,这个仓库就叫做 Registry。

企业可以用 Docker Registry 构建私有的 Registry。
Docker Hub(https://hub.docker.com) 是 Docker 为公众提供的托管 Registry,上面有很多现成的 image,为 Docker 用户提供了极大的便利。
Quay.io(https://quay.io/)是另一个公共托管 Registry,提供与 Docker Hub 类似的服务。
容器 OS
由于有容器 runtime,几乎所有的 Linux、MAC OS 和 Windows 都可以运行容器。但这不并没有妨碍容 器 OS 的问世。

容器 OS 是专门运行容器的操作系统。与常规 OS 相比,容器 OS 通常体积更小,启动更快。因为是为容器定制的 OS,通常它们运行容器的效率会更高。
目前已经存在不少容器 OS,CoreOS、atomic 和 ubuntu core 是其中的杰出代表。
下一节继续介绍容器平台技术和容器支持技术。
003 容器生态系统(续)
容器生态系统包含核心技术、平台技术和支持技术三个方面。上一节我们讨论了核心技术,今天讨论另外两个部分。
容器平台技术
容器核心技术使得容器能够在单个 host 上运行。而容器平台技术能够让容器作为集群在分布式环境中运行。

容器平台技术包括容器编排引擎、容器管理平台和基于容器的 PaaS。
容器编排引擎
基于容器的应用一般会采用微服务架构。在这种架构下,应用被划分为不同的组件,并以服务的形式运 行在各自的容器中,通过 API 对外提供服务。为了保证应用的高可用,每个组件都可能会运行多个相同 的容器。这些容器会组成集群,集群中的容器会根据业务需要被动态地创建、迁移和销毁。
大家可以看到,这样一个基于微服务架构的应用系统实际上是一个动态的可伸缩的系统。这对我们的部署环境提出了新的要求,我们需要有一种高效的方法来管理容器集群。而这,就是容器编排引擎要干的工作。
所谓编排(orchestration),通常包括容器管理、调度、集群定义和服务发现等。通过容器编排引擎, 容器被有机的组合成微服务应用,实现业务需求。

docker swarm 是 Docker 开发的容器编排引擎。
kubernetes 是 Google 领导开发的开源容器编排引擎,同时支持 Docker 和 CoreOS 容器。
mesos 是一个通用的集群资源调度平台,mesos 与 marathon 一起提供容器编排引擎功能。 以上三者是当前主流的容器编排引擎。
容器管理平台
容器管理平台是架构在容器编排引擎之上的一个更为通用的平台。通常容器管理平台能够支持多种编排引擎,抽象了编排引擎的底层实现细节,为用户提供更方便的功能,比如 application catalog 和一键应用部署等。

Rancher 和 ContainerShip 是容器管理平台的典型代表。
基于容器的 PaaS
基于容器的 PaaS 为微服务应用开发人员和公司提供了开发、部署和管理应用的平台,使用户不必关心底层基础设施而专注于应用的开发。

Deis、Flynn 和 Dokku 都是开源容器 PaaS 的代表。
容器支持技术
下面这些技术被用于支持基于容器的基础设施。

容器网络
容器的出现使网络拓扑变得更加动态和复杂。用户需要专门的解决方案来管理容器与容器,容器与其他实体之间的连通性和隔离性。

docker network 是 Docker 原生的网络解决方案。除此之外,我们还可以采用第三方开源解决方案,例如 flannel、weave 和 calico。不同的方案设计和实现方式不同,各有优势和特定,我们可以根据实际需
要来选型。
服务发现
动态变化是微服务应用的一大特点。当负载增加时,集群会自动创建新的容器;负载减小,多余的容器会被销毁。容器也会根据 host 的资源使用情况在不同 host 中迁移,容器的 IP 和端口也会随之发生变化。
在这种动态的环境下,必须要有一种机制让 client 能够知道如何访问容器提供的服务。这就是服务发现技术要完成的工作。
服务发现会保存容器集群中所有微服务最新的信息,比如 IP 和端口,并对外提供 API,提供服务查询功能。

etcd、consul 和 zookeeper 是服务发现的典型解决方案。
监控
监控对于基础架构非常重要,而容器的动态特征对监控提出更多挑战。
针对容器环境,已经涌现出很多监控工具和方案。

docker ps/top/stats 是 Docker 原生的命令行监控工具。除了命令行,Docker 也提供了 stats API,用户可以通过 HTTP 请求获取容器的状态信息。
sysdig、cAdvisor/Heapster 和 Weave Scope 是其他开源的容器监控方案。
数据管理
容器经常会在不同的 host 之间迁移,如何保证持久化数据也能够动态迁移,是 Flocker 这类数据管理工具提供的能力。

日志管理
日志为问题排查和事件管理提供了重要依据。

docker logs 是 Docker 原生的日志工具。而 logspout 对日志提供了路由功能,它可以收集不同容器的日志并转发给其他工具进行后处理。
安全性
对于年轻的容器,安全性一直是业界争论的焦点。

OpenSCAP 能够对容器镜像进行扫描,发现潜在的漏洞。
004 安装docker
环境选择
容器需要管理工具、runtime 和操作系统,我们的选择如下:
- 管理工具 - Docker Engine,Docker 最流行使用最广泛。
- runtime - runc,Docker 的默认 runtime
- 操作系统 - CentOS Stream8
安装操作系统
基于CentOS-Stream-8模板制作这个博客手册做出来的模板克隆一个虚拟机命名为docker,并配置静态IP 192.168.108.30,主机名改为docker





bash
[root@localhost ~]# hostnamectl set-hostname docker [root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.30/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes [root@localhost ~]# nmcli con up ens160
安装 Docker
Docker 支持几乎所有的 Linux 发行版,也支持 Mac 和 Windows。各操作系统的安装方法可以访问:https://docs.docker.com/engine/installation/
卸载旧版本(可选)
bash
[root@docker ~]# yum remove docker-ce
安装必要工具
bash
# devicemapper 存储驱动已经在 docker 18.09 版本中被废弃,所以在后续的安Docker装中无需安装devicemapper支持。
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 vim
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# yum makecache
Docker CE Stable - x86_64 57 kB/s | 66 kB 00:01
CentOS Stream 8 - BaseOS 8.3 kB/s | 3.9 kB 00:00
CentOS Stream 8 - AppStream 9.8 kB/s | 4.4 kB 00:00
Metadata cache created.
allinone部署
安装软件
bash
[root@docker ~]# yum install -y docker-ce
配置服务
bash
[root@docker ~]# systemctl enable docker.service --now
验证安装
查看docker版本
bash
[root@docker ~]# docker --version
Docker version 26.1.3, build b72abbb
查看docker状态
bash
[root@docker ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2025-09-03 13:51:07 CST; 36s ago
Docs:https://docs.docker.com
Main PID: 1813 (dockerd)
Tasks: 10
Memory: 135.7M
CGroup: /system.slice/docker.service
└─1813 /usr/bin/dockerd -H fd:// -- containerd=/run/containerd/containerd.sock
配置镜像加速器(阿里云)
阿里云官网:阿里云-计算,为了无法计算的价值


bash
[root@docker ~]# sudo mkdir -p /etc/docker
[root@docker ~]# sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://6iam7l3f.mirror.aliyuncs.com"]
}
EOF
[root@docker ~]# sudo systemctl daemon-reload
[root@docker ~]# sudo systemctl restart docker
#检查镜像加速器配置
[root@docker ~]# docker info
Client: Docker Engine - Community
Version: 26.1.3
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.14.0
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.27.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 26.1.3
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
runc version: v1.1.12-0-g51d5e94
init version: de40ad0
Security Options:
seccomp
Profile: builtin
Kernel Version: 4.18.0-553.6.1.el8.x86_64
Operating System: CentOS Stream 8
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.486GiB
Name: docker
ID: 96160847-9a97-40f4-997c-d12efaaef738
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
`https://6iam7l3f.mirror.aliyuncs.com/ <---看这里
Live Restore Enabled: false
配置镜像加速器(华为云)




bash
[root@docker ~]# vi /etc/docker/daemon.json {
{
"registry-mirrors": [ "https://4cec4ac9814d4e9eb6093dc611e07f27.mirror.swr.myhuaweicloud.com" ]
}
# 按"Esc",输入:wq保存并退出。
#重启容器引擎
[root@docker ~]# systemctl restart docker
#确认配置结果
[root@docker ~]# docker info
Client: Docker Engine - Community
Version: 26.1.3
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.14.0
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.27.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 26.1.3
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
runc version: v1.1.12-0-g51d5e94
init version: de40ad0
Security Options:
seccomp
Profile: builtin
Kernel Version: 4.18.0-553.6.1.el8.x86_64
Operating System: CentOS Stream 8
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.486GiB
Name: docker
ID: 96160847-9a97-40f4-997c-d12efaaef738
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
`https://4cec4ac9814d4e9eb6093dc611e07f27.mirror.swr.myhuaweicloud.com <---看这
Live Restore Enabled: false
运行第一个容器
环境就绪,马上运行第一个容器,执行命令:
bash
[root@docker ~]# docker run hello-world

其过程可以简单的描述为:
- 从本地查找hello-wrold镜像,没找到
- 从 Docker Hub 下载hello-world镜像。
- 启动hello-world容器。
清空刚才的实验环境:
bash
[root@docker ~]# docker rm -f $(docker ps -aq) #删除所有容器
[root@docker ~]# docker rmi -f hello-world #删除镜像hello-world
此刻docker环境没有问题了,关机拍摄快照

运行第二个容器
bash
[root@docker ~]# docker run -d -p 80:80 httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
852e50cd189d: Pull complete
67d51c33d390: Pull complete
b0ad2a3b9567: Pull complete
136f1f71f30c: Pull complete
01f8ace29294: Pull complete
Digest: sha256:fddc534b7f6bb6197855be559244adb11907d569aae1283db8e6ce8bb8f6f456
Status: Downloaded newer image for httpd:latest 817f24cca3514568f9b7a7cac6f183734077fb74caf4c62502acd2a4d0d29520
其过程可以简单的描述为:
- 从 Docker Hub 下载 httpd 镜像。镜像中已经安装好了 Apache HTTP Server。
- 启动 httpd 容器,并将容器的 80 端口映射到 host 的 80 端口。
下面我们可以通过浏览器验证容器是否正常工作。在浏览器中输入 http://your host os IP
bash
[root@docker ~]# curl 192.168.108.30
<html><body><h1>It works!</h1></body></html>

可以访问容器的 http 服务了,第一个容器运行成功!我们轻轻松松就拥有了一个 WEB 服务器。
005 docker C/S分离部署
基于CentOS-Stream-8模板制作这个博客手册做出来的模板克隆虚拟机命名为docker_client和docker_server

docker server端配置
配置ip 192.168.108.30
配置hostname docker_server
bash
[root@localhost ~]# hostnamectl set-hostname docker_server
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.30/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160
安装软件
bash
[root@docker_server ~]# yum install -y yum-utils device-mapper-persistent-data
lvm2 vim
[root@localhost ~]# yum-config-manager --add-repo
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker
ce.repo
[root@docker_server ~]# yum makecache
[root@docker_server ~]# yum install -y docker-ce
[root@docker_server ~]# systemctl enable docker.service --now
[root@docker_server ~]# vi /etc/docker/daemon.json
{
"registry-mirrors": [
"https://4cec4ac9814d4e9eb6093dc611e07f27.mirror.swr.myhuaweicloud.com" ]
}
# 按"Esc",输入:wq保存并退出。
#重启容器引擎
[root@docker_server ~]# systemctl restart docker
配置服务
bash
[root@docker_server ~]# vim /usr/lib/systemd/system/docker.service
# 在ExecStart参数中最后添加 -H tcp://0.0.0.0:2375,docker默认监听2375
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375
[root@docker_server ~]# systemctl daemon-reload
[root@docker_server ~]# systemctl restart docker.service
[root@docker_server ~]# systemctl stop firewalld
配置效果如下

验证
bash
[root@docker_server ~]# yum install lsof
[root@docker_server ~]# lsof -i :2375
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dockerd 5440 root 3u IPv6 44991 0t0 TCP *:docker (LISTEN)
docker_client端
配置ip 192.168.108.31
bash
[root@localhost ~]# hostnamectl set-hostname docker_client
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual
ipv4.addresses 192.168.108.31/24 ipv4.gateway 192.168.108.2 ipv4.dns
192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160
只安装docker客户端
bash
[root@docker-client ~]# yum install -y yum-utils device-mapper-persistent-data
lvm2 vim
[root@docker-client ~]# yum-config-manager --add-repo
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker
ce.repo
[root@docker-client ~]# yum makecache
[root@docker-client ~]# yum install -y docker-ce-cli
验证
bash
[root@docker_client ~]# docker run hello-world #client直接执行报错,没有装服务端
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is
the docker daemon running?.
See 'docker run --help'.
# client端连接server端执行命令
[root@docker-client ~]# docker -H 192.168.108.30 run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
[root@docker-client ~]# docker -H 192.168.108.30 images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d2c94e258dcb 17 months ago 13.3kB
#这里也可以切换到Server端查看现象
说明:client只做管理,image和container存储在server端。