文章目录

Docker 介绍(镜像与容器管理)

一、容器技术介绍

1.1 容器发展史

早期隔离思想

该阶段属于操作系统级虚拟化萌芽,各 BSD、商业 Unix 实现隔离,但是没有统一 Linux 原生方案。

  1. 1979 年:Unix chroot () 系统调用。Unix V7 引入 chroot,修改进程根目录,实现文件系统隔离。仅做目录隔离,没有 CPU、内存、网络隔离,是容器最早的技术原型。
# root 破解密码
# /dev/centos/root   /mnt/sysroot
mount -o rw,remount /mnt/sysroot
chroot /mnt/sysroot/
  1. 1998 年 FreeBSD Jails。FreeBSD 推出 Jails,在 chroot 基础上增加进程、网络隔离,可以在一台主机运行多个独立 “虚拟系统”,面向服务隔离,是现代容器思想重要实践。
  2. 2000 年 Solaris Zones。Solaris Zones,操作系统级虚拟化,CPU / 内存 / 网络 / 文件系统完整隔离,Oracle 商用操作系统容器方案。
Linux 内核关键技术

Namespace 做隔离,Cgroups 做资源限制,两大基石全部就位,Linux 容器底层能力完备。

  1. 2002:Linux 引入 PID Namespace。实现进程 ID 隔离,容器内部拥有独立 PID 编号。
  2. 2003:Linux 引入 Network Namespace。网络栈隔离,每个容器独立网卡、IP、路由表。
  3. 2004‑2006:IPC、Mount Namespace 陆续并入内核。
  • IPC Namespace:进程间通信隔离
  • Mount Namespace:挂载点隔离,容器可以拥有独立文件挂载视图
  1. 2007:Cgroups(Control Groups)并入 Linux 内核。由 Google 工程师开发,实现 CPU、内存、IO、网络带宽资源限制。
  2. 2008:User Namespace 开发迭代。实现用户 UID/GID 隔离,容器内部 root 不等于宿主机 root,解决容器权限安全问题,后续版本逐步完善。
LXC 容器诞生
  1. 2008:LXC(Linux Containers)项目启动。LXC 基于 Namespace + Cgroups 封装,世界上第一个完整 Linux 用户态容器工具。痛点:没有镜像机制,配置复杂,分发困难,主要面向运维专家。
  2. 2010:CloudFoundry Warden。VMware 推出 Warden,容器管理服务,做资源隔离与实例生命周期管理。
  3. 2013 dotCloud 内部项目孵化 Docker。dotCloud 是一家 PaaS 云厂商,内部做容器工具,解决 LXC 镜像、打包分发痛点。
Docker 爆发
  1. 2013‑06:Docker 0.1 正式对外发布。基于 LXC,核心创新:镜像分层、Dockerfile、镜像仓库、统一工具链。不再只是内核隔离工具,而是完整应用打包分发体系,容器迅速出圈。
  2. 2014‑06:Docker 1.0 正式版发布,生产可用。Docker Hub 公共镜像仓库大规模使用。
  3. 2014:Google 对外发布 Borg 论文。Borg 是 Google 内部大规模容器调度系统,是 Kubernetes 的思想源头;同时 Google 放出 lmctfy 容器工具。
  4. 2014 年 7 月:Docker 切换 libcontainer。抛弃 LXC,自研 libcontainer,直接调用 Linux 系统调用,不依赖 LXC 工具链,容器运行时独立。
  5. 2015‑06:OCI 开放容器基金会成立。Linux 基金会主导,Docker、Google、红帽等共同成立 OCI(Open Container Initiative),制定容器镜像规范、容器运行时规范,避免容器生态分裂。
Kubernetes 崛起
  1. 2015‑07:Kubernetes 1.0 发布。Google 开源 K8s,基于 Borg 经验,容器集群编排,实现调度、自愈、服务发现、滚动更新。标志容器从单机走向大规模集群。
  2. 2016:runc 正式发布。OCI 标准运行时,libcontainer 改名 runc,底层真正创建容器的工具;Docker 底层调用 runc。
  3. 2016:containerd 项目诞生。Docker 拆分出 containerd,高级容器运行时,管理镜像、容器生命周期,上层对接 docker、k8s,下层调用 runc。
  4. 2017:Kubernetes 进入 CNCF(云原生计算基金会)。K8s 移交 CNCF 托管,成为容器编排事实标准。Docker 公司商业受挫,Docker Swarm 编排逐渐边缘化。
  5. 2017‑2018:CRI 容器运行时接口成熟。K8s 定义 CRI 接口,K8s 不再强绑定 docker;cri‑containerd 把 containerd 适配 CRI。
云原生生态成熟
  1. 2019:Kubernetes 1.24 正式移除 dockershim。K8s 不再内置 Docker 适配,用户直接使用 containerd 作为 K8s 默认容器运行时。Docker 作为开发工具保留,集群层面不再是首选运行时。
  2. 安全容器发展
  • Kata Containers:轻量级虚拟机,内核隔离,强安全隔离;
  • gVisor:Google,用户态内核,隔离应用与宿主机内核。
  1. 其他 OCI 兼容运行时。nerdctl(containerd 的命令行工具,兼容 docker 命令)、crun(C 语言实现轻量 runc 替代)广泛使用。
  2. 2020‑2023:Podman + Buildah 普及。红帽 Podman,无守护进程容器工具,兼容 docker 命令,原生支持 OCI 标准。
  3. 2024‑2026:WebAssembly 容器、轻量容器兴起。Wasm‑OCI,将 Wasm 作为容器镜像,极低开销;K8s 对 Wasm 运行时支持增强。
极简时间轴表格

表格

时间里程碑事件核心价值
1979Unix chroot文件系统隔离原型
1998FreeBSD Jails完整 OS 级隔离雏形
2007Linux Cgroups 合入内核资源限制基石
2008LXC 项目诞生第一个 Linux 容器工具
2013Docker 发布镜像 + Dockerfile,容器大众化
2015OCI 成立;K8s 1.0标准化 + 集群编排时代开启
2016runc、containerd分层容器运行时架构
2017K8s 移交 CNCFK8s 成为编排事实标准
2022K8s 彻底移除 dockershimcontainerd 成为 K8s 默认运行时
2023 至今Wasm 容器、安全容器轻量、强隔离新方向

1.2 什么是容器?

容器是操作系统级虚拟化技术,在同一台宿主机操作系统之上,把应用程序以及它的依赖库、配置文件、环境变量打包在一起,实现相互隔离的运行环境。

传统的虚拟化技术,比如 VMWare, KVM, Xen,目标是创建完整的虚拟机。为了运行应用,除了部署应用本身及其依赖(通常几十 MB),还得安装整个操作系统(几十 GB)。

  • 所有的容器共享同一个 Host OS,这使得容器在体积上要比虚拟机小很多。
  • 启动容器不需要启动整个操作系统,容器部署和启动速度更快,开销更小,也更容易迁移。
  • 容器可以在核心 CPU 本地运行指令,不需要任何专门的解释机制。与虚拟化相比,这样既不需要指令级模拟,也不需要即时编译。

表格

特性容器虚拟机
启动速度秒级分钟级
性能接近原生较弱
内存代价很小较多
硬盘使用一般为 MB一般为 GB
运行密度单机支持上千个容器一般几十个
隔离性安全隔离完全隔离
迁移性优秀一般

1.3 容器解决的问题

开发环境、测试环境、生产环境环境不一致,应用依赖复杂,多环境部署会形成 N×M 的维护矩阵。 借鉴现实世界集装箱思想:把应用 + 依赖打包成标准化 “集装箱”,一次打包,到处运行。

“容器” 和 “集装箱” 英文都是Container。

1.4 容器的优势

  • 开发:Build Once, Run Anywhere 环境隔离、可重复,打包完成后任意机器运行,隔离宿主机环境。
  • 运维:Configure Once, Run Anything 只维护标准运行时,消除开发、测试、生产环境差异。

1.5 容器的特性

表格

特性集装箱容器
打包对象几乎任何货物任何软件及其依赖
硬件依赖标准形状和接口允许集装箱被装卸到各种交通工具,整个运输过程无需打开容器无需修改便可运行在几乎所有的平台上 – 虚拟机、物理机、公有云、私有云
隔离性集装箱可以重叠起来一起运输,香蕉再也不会被铁桶压烂了资源、网络、库都是隔离的,不会出现依赖问题
自动化标准接口使集装箱很容易自动装卸和移动提供 run, start, stop 等标准化操作,非常适合自动化
高效性无需开箱,可在各种交通工具间快速搬运轻量级,能够快速启动和迁移
职责分工货主只需考虑把什么放到集装箱里;承运方只需关心怎样运输集装箱开发人员只需考虑怎么写代码;运维人员只需关心如何配置基础环境

二、容器生态系统

2.1 容器核心技术

包含:容器规范、容器 runtime、容器管理工具、容器定义工具、Registry、容器 OS。

  1. OCI 开放容器规范:runtime spec(运行时规范)、image format spec(镜像格式规范),保证跨厂商兼容。
  2. Runtime 运行时:lxc、runc(OCI 标准,docker 默认底层)、rkt。
  3. 管理工具:lxd、docker engine、rkt cli。
  4. 定义工具:docker image、Dockerfile、ACI。
  5. Registry 镜像仓库:Docker Hub、私有 Registry、Quay.io。
  6. 容器 OS:专门运行容器的操作系统,CoreOS、atomic、ubuntu core。

2.2 容器平台技术

  • 容器编排引擎:Docker Swarm、Kubernetes、Mesos+Marathon,负责集群容器调度、自愈、服务发现。
  • 容器管理平台
    • 开源:Rancher、OpenShift、KubeSphere、Portainer、Lens
    • 云厂商托管:AWS EKS、Azure AKS、阿里云 ACK
  • PaaS 平台:Deis、Flynn、Dokku。

2.3 容器支持技术

  • 容器网络:docker network、flannel、weave、calico
  • 服务发现:etcd、consul、zookeeper
  • 监控:docker stats、cAdvisor、sysdig、Weave Scope
  • 数据管理:Flocker
  • 日志:docker logs、logspout
  • 安全:OpenSCAP 镜像漏洞扫描

三、Docker 介绍

Docker 是 Go 语言开发开源容器项目,2013 年 dotCloud 公司推出。核心是镜像分层机制,简化容器使用。Docker 是轻量级沙盒,容器互相隔离,可以网络互通。

3.1 Docker 架构(C/S 客户端服务端架构)

在这里插入图片描述

组件:

  1. Client 客户端:执行 docker 命令,发送请求给 daemon,不直接操作容器。常用命令docker build/pull/run。
  2. Docker Host 宿主机
    • Docker daemon:后台守护进程,真正处理镜像、容器所有操作。
    • Images 镜像:只读模板,容器的模板,分层存储,不能直接运行镜像。
    • Containers 容器:镜像运行实例;在镜像之上增加一层读写层;本质宿主机上被 Namespace、Cgroups 管控的进程;删除容器读写层数据丢失。
  3. Registry 镜像仓库:存放镜像,Docker Hub 为公共仓库;支持私有仓库;docker pull下载、docker push上传镜像。

完整交互流程:

  1. 用户 Client 执行docker run nginx,发送请求给 daemon。
  2. daemon 访问 Registry 下载 nginx 镜像保存本地。
  3. daemon 使用镜像创建网络存储资源,启动容器。

3.2 Docker 版本演进

  1. 2013‑2017‑02:语义化 1.x,格式主。次. 补丁;1.13 为最后 1.x 版本。
  2. 2017‑03 ~2022‑06:日历版本 CE/EE 社区版企业版,YY.MM.Patch;20.10 经典稳定版本。
  3. 2023‑02 至今:回归语义化 23.x+,默认启用 BuildKit。

3.3 搭建学习环境 CentOS7

在这里插入图片描述

环境准备本地 yum 源
[root@docker ~]# mkdir /dvd
[root@docker ~]# cp /etc/fstab /etc/fstab.bak
[root@docker ~]# echo '/dev/sr0 /dvd iso9660 defaults 0 0'>> /etc/fstab
[root@docker ~]# mount /dvd
mount: /dev/sr0 写保护,将以只读方式挂载
[root@docker ~]# ls /dvd
CentOS_BuildTag  EULA  images    LiveOS    repodata              RPM-GPG-KEY-CentOS-Testing-7
EFI              GPL   isolinux  Packages  RPM-GPG-KEY-CentOS-7  TRANS.TBL
# 如果提示如下,则编辑虚拟机:关联对应iso文件
[root@docker ~]# mount /dvd
mount: /dev/sr0 写保护,将以只读方式挂载
mount: 在 /dev/sr0 上找不到媒体
[root@docker ~]# mkdir /etc/yum.repos.d/bak
[root@docker ~]# mv /etc/yum.repos.d/*repo /etc/yum.repos.d/bak
[root@docker ~]# vim /etc/yum.repos.d/dvd.repo
[dvd]
name=local repo from dvd
baseurl=file:///dvd
gpgcheck=0
[root@docker ~]# yum clean all
已加载插件:fastestmirror
正在清理软件源: dvd
Cleaning up list of fastest mirrors
Other repos take up 634 M of disk space (use --verbose for details)
[root@docker ~]# yum makecache

防火墙配置

[root@docker ~]# systemctl enable firewalld.service --now
[root@docker ~]# firewall-cmd --set-default-zone=trusted

配置 docker-ce 华为源

[root@docker ~]# cat > /etc/yum.repos.d/docker-ce.repo <<'EOF'
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.huaweicloud.com/docker-ce/linux/centos/7/$basearch/stable
enabled=1
gpgcheck=0
EOF
all‑in‑one 安装 docker
[root@docker ~]# yum install -y docker-ce
# 启动服务
[root@docker ~]# systemctl enable docker.service --now

配置镜像加速

[root@docker ~]# mkdir -p /etc/docker 
[root@docker ~]# tee /etc/docker/daemon.json <<'EOF'
{
  "insecure-registries": ["hub.laoma.cloud"],
  "registry-mirrors": ["http://hub.laoma.cloud","https://docker.m.daocloud.io"]
}
EOF
[root@docker ~]# systemctl restart docker

验证安装

# 查看docker版本
[root@docker ~]# docker --version
# 运行第一个容器
[root@docker ~]# docker run hello-world
# 运行httpd web容器
[root@docker ~]# docker run -d -p 80:80 httpd
# 访问测试
[root@docker ~]# curl 10.1.8.130
C/S 分离部署(服务端暴露 2375 端口)

server 端

[root@docker ~]# dnf install -y docker-ce
[root@docker ~]# vim /usr/lib/systemd/system/docker.service
# ExecStart增加 -H tcp://0.0.0.0:2375
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl enable docker.service --now
# 验证端口监听
[root@docker ~]# lsof -i :2375

client 客户端,仅安装 cli

[root@client ~]# dnf install -y docker-ce-cli
# 远程操作远端docker服务
[root@client ~]# docker -H 10.1.8.130 run hello-world
[root@client ~]# docker -H 10.1.8.130 images

四、Docker 镜像管理

镜像:只读模板,分层存储,容器从镜像实例化而来;本地存储路径/var/lib/docker。

4.1 search 搜索镜像

docker search --help
# 搜索3星以上centos镜像
docker search --filter stars=3 centos

注意:国内环境 docker search 经常访问 hub 超时。

查询远程镜像所有 tag 版本 docker 没有原生命令,使用 hub api:

# 查询官方nginx标签
curl -s "https://registry.hub.docker.com/v2/repositories/library/nginx/tags/" | jq '.results[].name'
# 查询harbor私有仓库镜像标签
curl -s "http://hub.laoma.cloud/api/v2.0/projects/library/repositories/nginx/artifacts" | jq -r '.[].tags[].name' | sort -V

4.2 pull 获取镜像

语法:docker image pull [镜像名:tag],tag 默认 latest

docker image pull --help
# 拉取centos8
docker image pull centos:8
# 拉取第三方仓库镜像
docker image pull registry.access.redhat.com/ubi8

4.3 ls 列出本地镜像

docker image ls --help
docker image ls
# 格式化输出只打印仓库和tag
docker image ls --format "{{.Repository}}:{{.Tag}}"

4.4 tag 镜像打标签

tag 只是给同一个镜像 ID 增加别名,不会复制镜像,多个 tag 共享同一份镜像数据。

docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
docker image tag centos:8 myos
docker image tag centos:8 myos:v1
docker image ls

镜像 tag 最佳实践:

  • myimage:1.9.1固定小版本;
  • myimage:1.9代表 1.9 分支最新;
  • myimage:1代表 1 主分支最新;
  • myimage:latest指向最新版本。

4.5 inspect 查看镜像详细元数据

docker image inspect myos
# 使用go模板过滤字段
docker image inspect myos -f '{{.Architecture}}'
docker image inspect myos -f '{{.Os}}'

4.6 history 查看镜像分层构建历史

docker image history myos
# --no‑trunc 不截断输出
docker image history myos --no-trunc

4.7 rm 删除镜像

docker image rm centos:8
# 删除镜像ID
docker image rm 958373fdd7e8

关键点:同一个镜像多个 tag 时,rm 只是删除 tag 别名;只有删除最后一个 tag 才真正删除镜像层;被容器正在使用镜像需要‑f强制删除。

4.8 prune 清理无用镜像

# 只清理悬空dangling镜像
docker image prune
# -a 删除所有没有被容器关联的镜像
docker image prune -a

4.9 save 将镜像导出 tar 包

save 保存完整镜像分层、元数据、历史。

docker image save --help
# 保存单个镜像
docker save httpd -o httpd.tar
# 一次性保存多个镜像
docker save httpd hello-world -o images.tar
ls *.tar

4.10 load 从 tar 包导入镜像

docker image load -i images.tar
docker image ls

⚠️注意:save输出的 tar,只能用load导入;不能用来导入 export 导出的容器 tar 包。

4.11 push 推送镜像到仓库

推送前需要登录仓库,镜像名称格式必须为用户名/镜像名:tag

docker login
docker image tag hello-world:latest mage16196/myhello
docker image push mage16196/myhello

五、Docker 容器管理

容器:镜像运行实例;本质宿主机进程,被 Namespace 隔离、Cgroups 限制资源;读写层保存运行数据;删除容器读写层数据丢失。

5.1 ls 查看容器列表

docker container ls --help
# 只看运行中
docker container ls
# -a 查看全部(包含停止退出)
docker container ls -a
# 过滤状态为exited的容器
docker container ls -f status=exited

5.2 create 创建容器(只创建,不启动)

docker container create centos:8
# 指定名字、主机名、交互式终端
docker container create -it --name myos -h myos centos:8

5.3 start 启动已经创建的容器

docker container start 12ea7f1
# -ai 启动并且附加交互终端
docker container start -ai myos

5.4 top 查看容器内部进程

docker container top be05a7c31635

5.5 stats 实时查看容器资源监控

docker container stats
# 指定单个容器
docker container stats be05a7c31635
# 格式化输出
docker container stats --format '{{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}'

5.6 inspect 查看容器完整详细信息

docker container inspect be05a7c31635
# 模板提取PID
docker container inspect be05a7c31635 -f '{{.State.Pid}}'
# 获取容器IP
docker container inspect be05a7c31635 -f '{{.NetworkSettings.Networks.bridge.IPAddress}}'

5.7 run 创建并且启动容器(=create + start)

docker container run centos:8 echo hello world
# 交互式终端
docker container run -it centos:8

常用 run 参数

# -d 后台守护态运行
docker run -d centos:8 sh -c 'while true;do echo sleep 5;sleep 5;done'

# --rm:容器退出自动删除(临时测试)
docker container run --name test --rm centos:8 echo hello world

# --restart=always 退出自动重启,docker服务重启容器也自动拉起
docker container run --name test2 -it --restart=always centos:8

docker run 执行完整流程:

  1. 本地无镜像,则拉取镜像;
  2. 创建容器,分配读写层;
  3. 创建网桥虚拟网卡,分配 IP;
  4. 执行容器内程序;
  5. 应用进程退出,则容器终止。

5.8 logs 查看容器控制台日志

docker logs 5bd4eb2e
# -f 持续跟踪日志输出
docker logs -f 5bd4eb2e

5.9 进入运行中容器两种方式

attach 附加到容器主进程

多个窗口 attach 会同步输出;退出会影响主进程,不推荐日常使用。

docker container attach 5bd4eb2e348b
exec 在容器内部执行新进程(推荐)

不影响原有主程序,新开终端。

docker container exec -it 5bd4eb2e348b bash

5.10 stop /kill 停止容器

# stop:优雅停止,先发SIGTERM,超时发送SIGKILL,默认等待10秒
docker container stop test2
# kill:直接发送SIGKILL强制杀死
docker container kill be05a7c31635

5.11 restart 重启容器

docker container restart be05a7c31635

5.12 pause /unpause 暂停恢复容器

# 暂停容器所有进程
docker container pause 5bd4eb2e348b
# 恢复运行
docker container unpause 5bd4eb2e348b

5.13 rm 删除容器

默认只能删除停止状态容器;‑f强制删除运行容器。

docker container rm test1
# 强制删除运行容器
docker container rm -f myos

5.14 prune 批量清理所有停止的容器

docker container prune -f

5.15 export /import 容器导出导入

export:导出当前容器文件系统快照,丢失镜像分层、构建历史;导出的 tar 不能使用load导入,只能用import。

# export导出容器文件系统
docker container export be05a7c31635 -o myhttpd.tar
# import把tar导入成为新镜像
docker image import myhttpd.tar myweb:v1
docker image ls
save VS export 对比总结

表格

命令对象保存内容导入工具特点
docker save镜像完整分层、元数据、构建历史docker load镜像完整备份迁移
docker export容器容器当前文件系统快照,丢失历史docker import快照,生成全新扁平镜像

思考:docker container export导出的 tar 包,执行docker image load会直接报错。


小结

  1. 容器底层两大基石:Namespace 做隔离,Cgroups 做资源限制。
  2. Docker 架构 C/S,daemon 后台处理所有工作,客户端只是发送指令。
  3. 镜像只读,容器读写;镜像模板,容器运行实例。
  4. save‑load 用于镜像迁移;export‑import 用于容器快照生成镜像,丢失分层历史。
  5. 进入容器优先docker exec -it,不推荐 attach。
  6. docker run 等价于 docker create + docker start;–rm 适合一次性测试容器;–restart 实现开机自动恢复容器。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐