docker
docker容器
什么是容器
- 容器是一种基础工具;泛指任何可以用于容纳其他物品的工具,可以部分或完全封闭,被用于容纳、储存、运输物品;物体可以被放置在容器中,而容器则可以保护内容物;
linux容器技术
Linux容器其实并不是什么新概念。最早的容器技术可以追遡到1982年Unix系列操作系统上的chroot工具(直到今天,主流的Unix、Linux操作系统仍然支持和带有该工具)。
docker的发展史
很久以前
2008年,Solomon Hykes 和他的朋友 Kamel Founadi、Sebastien Pahl 共同创立了一家名为 DotCloud 的公司,目标是利用一种叫做容器的技术来创建他们称作是“大规模的创新工具”:任何人都可以使用的编程工具。
2010年,dotCloud获得了创业孵化器Y Combinator的支持,并开始吸引到一些真正的投资,在接下来的3年中,dotCloud内部孵化了一款名为Docker的产品。
2013年
2013 年 3 月 Docker 创始人 Solomon Hykes 在 PyCon 大会上的演讲中首次公开介绍了 Docker 这一产品。在2013 年 PyCon 大会之后,Docker 的创新式镜像格式以及容器运行时迅速成为社区、客户和更广泛行业的实际标准和基石。Docker 的强大之处在于它通过可移植的形式和易于使用的工具在应用程序和基础设施之间创造了独立性。其结果是,Docker将容器技术大众化,并解决了困扰数百万开发人员的“matrix from hell”问题,使容器技术成为主流。
2013年3月20日,dotCloud发布了 Docker 的首个版本,并将Docker源码进行开源。
2013年9月 红帽公司成为Docker的主要合作伙伴,利用Docker来驱动他的OpenShift云业务。随后,谷歌、亚马逊以及DigitalOcean也迅速的在其云服务平台提供了Docker的支持。主流云厂商的加入,加速Docker的发展进度。
随着Docker技术的开源,此项技术能够将Linux容器中的应用代码打包并轻松的在服务器之间迁移,Docker技术瞬时的风靡了全球,2013年底DotCloud Inc则更名为Docker Inc,并全力的主攻到Docker项目开发中。
2014年
2014年6月的DockerCon大会上Docker正式发布了Docker 1.0 版本。这也意味着Docker的稳定性和可靠性已经基本满足了生产环境的运行需求。会议上同时发布Docker Image的镜像仓库Docker Hub,并指出已经有超过14,000个Docker化的应用存储在他们的publc registry中。
也是同样的2014年6月,基于谷歌内部强大的Borg系统而开发出来的kubernetes横空处世,刷新了人们对容器的理解。
2014年8月份,Docker Inc宣布将用于PaaS业务服务的DotCloud软件出售给德国柏林的PaaS服务厂商CloudControl,自此以后,DotCloud正式的和Docker分道扬镳了。
2014年12月举行的DockerConEU大会上,Docker Swarm 和Docker Machine同时面世。Docker Swarm是一个Docker集群管理工具,而Docker Machine是部署Docker主机的命令工具。
2014年12月里,CoreOS宣布开发自家的容器运行环境rkt以及appc容器规范。
2015年
容器技术不只Docker,很早之前Google就投资了CoreOS来做竞争的容器--Rocket。那时是三家鼎立:Docker/Rocket/Warden,为了避免惨烈的竞争,大家终于统一意见,决定成立固定的标准来良好发展容器技术。
2015年6月,由Docker、IBM、微软、红帽及Google等厂商所组成的开放容器项目OCP联盟成立,该项目旨在建立软件容器的通用标准。OCP成立于Linux基金会之下,其使命是使用户和公司能够继续创新和开发基于容器的解决方案,并充满信心地保护其先前的开发工作,并且不会造成行业分散。作为该计划的一部分,Docker将捐赠其软件容器格式,运行时以及相关规范的代码。应用容器规范(“ appc”)计划的领导者,包括创始成员CoreOS,也将把他们的技术领导力和支持带到OCP。
2015 年,Docker 发布了 runC工具,runc是根据OCI标准生成的一个cli工具,一个轻量级的跨平台的容器运行时命令行小工具,可以直接利用 libcontainer 运行容器,而无需通过 docker engine。runC 的目标是使标准容器在任何地方都可用。
2016年
2016年6月的DockerCon上,Docker宣布了Open Container Initiative的正式成立。OCI意在业界一起合作,开发一个开放的、标准的容器格式和runtime。OCI也属于Linux基金会的协作项目,一直秉承着开放的模式来管理
2016年,OCI标准制定后,Docker 将 containerd 独立拆分,并将其捐赠给了社区。将这个组件分解为一个单独的项目,使得 docker 将容器的管理功能移出 docker 的核心引擎并移入一个单独的守护进程(即 containerd)。
在2016年,人们认识到容器技术本身的价值时在于容器的编排,而此时的Docker项目令人惊讶的放弃了Swarm项目,而是想将容器的编排和集群的管理功能添加到Docker项目当中。而Kubernetes却与Docker不同的是推进民主化架构,使得通过暴露Kubernetes API的方法,让更多的人来不断丰富kubernetes的插件。
2017年
从2013年3月开始推出0.1.0版本,到17年2月1.13的版本都采用x.x的形式。从 2017 年第一季度开始,Docker 版本号遵循 YY.MM-xx 格式。
2017 年是容器成为主流技术的一年,这就是为什么 Docker 在 Linux 之外支持众多平台的原因(Docker for Mac,Docker for Windows,Docker for AWS,GCP 等)。
2017 年于 Austin 举办的 DockerCon 上开源Docker项目正式命名为 Moby 项目。由于这次改名,GitHub 上的 docker/docker 库也被转移到了 moby/moby,并且拥有了项目自己的 Logo,如下图所示。
于此同时,将Docker本身拆分为Docker-CE免费版和Docker-EE商业版。
Docker-CE目前是docker公司维护的开源项目,是一个基于Moby项目的免费的容器产品。
Docker-EE目前是docker公司维护的闭源项目,是docker公司的商业产品。
至此,容器天下三分。其中Moby由社区维护,Docker-CE由Docker公司维护,Docker-EE是Docker公司闭源的商业产品。
2018年
2018年3月 Docker 公司创始人Solomon Hykes 在 Docker 博客上宣布已正式从 Docker 公司离职,不再担任公司的日常运作工作。Solomon Hykes 表示,他未来的身份将是 Docker 的董事会成员、主要股东,以及 Docker 维护者,但不再负责担任公司的日常工作。
2019年及未来
2019年容器市场基本趋于稳定,一切都向着优化改进方向发展。Docker公司是底层容器引擎及运行时的。容器的编排进过几轮的激烈竞争,基本是GOOGLE的Kubernetes一家独大。
新的战斗已经由容器和编排的战场,逐渐迁移到应用领域。云原生CNCF将引领新的技术方向,微服务、ServcieMesh、Envoy、ServerLess等正在路上
docker基础、用法
什么是docker
docker是容器技术的一个前端工具,容器是内核的一项技术,docker只是把这一项技术的使用得以简化,使之普及而已。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
docker的工作方式
为了使容器的使用更加易于管理,docker采取一个用户空间只跑一个业务进程的方式,在一个容器内只运行一个进程,比如我们要在一台主机上安装一个nginx和一个tomcat,那么nginx就运行在nginx的容器中,tomcat运行在tomcat的容器中,二者用容器间的通信逻辑来进行通信。
使用docker的优劣:
- 删除一个容器不会影响其他容器
- 调试不便,占空间(每个容器中都必须自带调试工具,比如ps命令)
- 分发容易,真正意义上一次编写到处运行,比java的跨平台更彻底
- 部署容易,无论底层系统是什么,只要有docker,直接run就可以了
- 分层构建,联合挂载
在容器中有数据称作有状态,没有数据称作无状态。在容器的使用中,我们应以有状态为耻,以无状态为荣。数据不应该放在容器中,而应放置于外部存储中,通过挂载到容器中从而进行数据的存储。
docker架构
docker镜像宇镜像仓库
为什么镜像仓库名字是Registry而不是repository?
在docker中仓库的名字是以应用的名称取名的。
镜像是静态的,而容器是动态的,容器有其生命周期,镜像与容器的关系类似于程序与进程的关系。镜像类似于文件系统中的程序文件,而容器则类似于将一个程序运行起来的状态,也即进程。所以容器是可以删除的,容器被删除后其镜像是不会被删除的。
docker对象
使用 Docker 时,您正在创建和使用映像、容器、网络、卷、插件和其他对象。
- 图像
- 映像是一个只读模板,其中包含有关创建 docker 容器的说明。
- 通常,一个映像基于另一个映像,并具有一些额外的自定义。
- 您可以创建自己的映像,也可以仅使用其他人创建并在注册表中发布的映像。
- 器皿
- 控制器是映像的可运行实例。
- 您可以使用 Docker API 或 CLI 创建、运行、停止、移动或删除容器。
- 可以将容器连接到一个或多个网络,将存储附加到该容器,甚至可以基于其当前状态创建新映像。
docker安装以及使用
docker安装
[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost yum.repos.d]# wget https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
--2022-08-06 19:56:10-- https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
Resolving mirrors.tuna.tsinghua.edu.cn (mirrors.tuna.tsinghua.edu.cn)... 101.6.15.130, 2402:f000:1:400::2
Connecting to mirrors.tuna.tsinghua.edu.cn (mirrors.tuna.tsinghua.edu.cn)|101.6.15.130|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1919 (1.9K) [application/octet-stream]
Saving to: 'docker-ce.repo'
docker-ce.repo 100%[===================>] 1.87K --.-KB/s in 0s
2022-08-06 19:56:10 (34.3 MB/s) - 'docker-ce.repo' saved [1919/1919]
[root@localhost yum.repos.d]# sed -i 's@https://download.docker.com@https://mirrors.tuna.tsinghua.edu.cn/docker-ce@g' docker-ce.repo
[root@localhost yum.repos.d]# dnf -y install docker-ce
配置镜像加速器
docker-ce的配置文件是/etc/docker/daemon.json,此文件默认不存在,需要我们手动创建并进行配置,而docker的加速就是通过配置此文件来实现的。
docker的加速有多种方式:
- docker cn
- 中国科技大学加速器
- 阿里云加速器(需要通过阿里云开发者平台注册帐号,免费使用个人私有的加速器)
[root@localhost ~]# sudo mkdir -p /etc/docker
[root@localhost ~]# sudo tee /etc/docker/daemon.json <<-'EOF'
> {
> "registry-mirrors": ["https://rlsyow3c.mirror.aliyuncs.com"]
> }
> EOF
{
"registry-mirrors": ["https://rlsyow3c.mirror.aliyuncs.com"]
}
[root@localhost ~]# sudo systemctl daemon-reload
[root@localhost ~]# sudo systemctl restart docker
docker常用操作
命令 | 功能 |
---|---|
docker search | 在Docker Hub上查找镜像 |
docker pull | 从镜像仓库中拉取或者更新指定镜像 |
docker images | 列出本地镜像 |
docker create | 创建一个新的容器但不启动它 |
docker start | 启动容器 |
docker run | 创建一个新的容器并运行一个命令 |
docker attach | 连接到运行的容器 |
docker ps | 列出容器 |
docker logs | 查看容器日志 |
docker restart | 重启容器 |
docker stop | 停止容器 |
docker kill | 干掉一个或多个运行中的容器 |
docker rm | 删除一个或多个容器 |
docker exec | 在运行的容器中运行命令 |
docker info | 显示整个系统的信息 |
docker inspect | 返回Docker对象的低级信息 |
[root@localhost ~]# systemctl enable docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
[root@localhost ~]# docker version //显示Docker版本信息
Client: Docker Engine - Community
Version: 20.10.17
API version: 1.41
Go version: go1.17.11
Git commit: 100c701
Built: Mon Jun 6 23:03:11 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.17
API version: 1.41 (minimum version 1.12)
Go version: go1.17.11
Git commit: a89b842
Built: Mon Jun 6 23:01:29 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.6
GitCommit: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc:
Version: 1.1.2
GitCommit: v1.1.2-0-ga916309
docker-init:
Version: 0.19.0
GitCommit: de40ad0
[root@localhost ~]# docker info //显示整个系统的信息
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Docker Buildx (Docker Inc., v0.8.2-docker)
scan: Docker Scan (Docker Inc., v0.17.0)
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 20.10.17
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
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 logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
Default Runtime: runc
Init Binary: docker-init
containerd version: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc version: v1.1.2-0-ga916309
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 4.18.0-394.el8.x86_64
Operating System: CentOS Stream 8
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.555GiB
Name: localhost.localdomain
ID: 66JJ:ADV4:GQXX:Z57U:UFOQ:TOKN:7ITL:OF35:NNBU:CZWM:S5QX:DPPQ
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://rlsyow3c.mirror.aliyuncs.com/
Live Restore Enabled: false
//docker search 在Docker Hub上查找镜像
[root@localhost ~]# docker search httpd
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
httpd The Apache HTTP Server Project 4109 [OK]
centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui… 44
centos/httpd 35 [OK]
hypoport/httpd-cgi httpd-cgi 2 [OK]
clearlinux/httpd httpd HyperText Transfer Protocol (HTTP) ser… 2
solsson/httpd-openidc mod_auth_openidc on official httpd image, ve… 2 [OK]
...省略
//docker pull 从镜像仓库中拉取或者更新指定镜像
[root@localhost ~]# docker pull httpd
Using default tag: latest
latest: Pulling from library/httpd
a2abf6c4d29d: Pull complete
dcc4698797c8: Pull complete
41c22baa66ec: Pull complete
67283bbdd4a0: Pull complete
d982c879c57e: Pull complete
Digest: sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
//docker images 列出本地镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest dabbfbe0c57b 7 months ago 144MB
//docker create 创建一个新的容器但不启动它
[root@localhost ~]# docker create --name web -p 80:80 httpd
b370c499ea7728c5c2e16ae86867d4f15269c1d0fd1571001874576d4e9cc6d9
//docker start 启动容器,可以用id或者名字
[root@localhost ~]# docker start web
web
//docker ps 列出容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b370c499ea77 httpd "httpd-foreground" 2 minutes ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp web
//docker stop 停止容器
[root@localhost ~]# docker stop web
web
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b370c499ea77 httpd "httpd-foreground" 3 minutes ago Exited (0) 14 seconds ago web
//docker restart 重启容器
[root@localhost ~]# docker restart web
web
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b370c499ea77 httpd "httpd-foreground" 3 minutes ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp web
//docker logs 查看容器日志
[root@localhost ~]# docker logs web
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Sat Aug 06 12:07:52.217160 2022] [mpm_event:notice] [pid 1:tid 140265235066176] AH00489: Apache/2.4.52 (Unix) configured -- resuming normal operations
[Sat Aug 06 12:07:52.217296 2022] [core:notice] [pid 1:tid 140265235066176] AH00094: Command line: 'httpd -D FOREGROUND'
..省略
//docker kill 干掉一个或多个运行中的容器
[root@localhost ~]# docker kill web
web
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b370c499ea77 httpd "httpd-foreground" 11 minutes ago Exited (137) 12 seconds ago web
//docker rm 删除一个或多个容器,运行时不能删除
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b370c499ea77 httpd "httpd-foreground" 13 minutes ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp web
[root@localhost ~]# docker stop web
web
[root@localhost ~]# docker rm web
web
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//docker run 创建一个新的容器并运行一个命令
[root@localhost ~]# docker run -it --name test httpd /bin/sh
#
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b9250cc81ab httpd "/bin/sh" About a minute ago Up 2 seconds 80/tcp test
//docker attach 连接到运行的容器
[root@localhost ~]# docker attach test
exit //exit退出后会自动关闭
//docker exec 在运行的容器中运行命令
[root@localhost ~]# docker start test
test
[root@localhost ~]# docker exec -it test /bin/sh
# exit //使用exec进入后退出不会停止运行
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b9250cc81ab httpd "/bin/sh" 4 minutes ago Up 26 seconds 80/tcp test
//docker inspect 返回Docker对象的低级信息
[root@localhost ~]# docker inspect test
[
{
"Id": "4b9250cc81ab76b7e90d3c4211122e0a6434325087e86822c2ad16078f09fd7d",
"Created": "2022-08-06T12:21:38.021007993Z",
"Path": "/bin/sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 87566,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-08-06T12:25:35.212725872Z",
"FinishedAt": "2022-08-06T12:24:49.306464111Z"
},
"Image": "sha256:dabbfbe0c57b6e5cd4bc089818d3f664acfad496dc741c9a501e72d15e803b34",
"ResolvConfPath": "/var/lib/docker/containers/4b9250cc81ab76b7e90d3c4211122e0a6434325087e86822c2ad16078f09fd7d/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/4b9250cc81ab76b7e90d3c4211122e0a6434325087e86822c2ad16078f09fd7d/hostname",
"HostsPath": "/var/lib/docker/containers/4b9250cc81ab76b7e90d3c4211122e0a6434325087e86822c2ad16078f09fd7d/hosts",
"LogPath": "/var/lib/docker/containers/4b9250cc81ab76b7e90d3c4211122e0a6434325087e86822c2ad16078f09fd7d/4b9250cc81ab76b7e90d3c4211122e0a6434325087e86822c2ad16078f09fd7d-json.log",
"Name": "/test",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/997a483a7287904346ca71cffb303b095fdea4d101972c4452bec37de57d6ca3-init/diff:/var/lib/docker/overlay2/7ae93e8e325514d5a09db8e37b1cdeecc3b0e3724c33c800be9e8189712bf09a/diff:/var/lib/docker/overlay2/d931b235e0eab986d193383d0c9c0c2f98b65f1232f979e406b227c874cb12ae/diff:/var/lib/docker/overlay2/92381e7caba93f601b51082ef822ca35042d43a051855ffe10dc5b6fc3089b4e/diff:/var/lib/docker/overlay2/bb9e13344cf33a59f55362e0eae51aeefa68766751d0de07211e46d78c050f1c/diff:/var/lib/docker/overlay2/c2f4ae4527e6a4bbde256fc35af5bfaa082ae3cb94f529fce4263d7a6e09761b/diff",
"MergedDir": "/var/lib/docker/overlay2/997a483a7287904346ca71cffb303b095fdea4d101972c4452bec37de57d6ca3/merged",
"UpperDir": "/var/lib/docker/overlay2/997a483a7287904346ca71cffb303b095fdea4d101972c4452bec37de57d6ca3/diff",
"WorkDir": "/var/lib/docker/overlay2/997a483a7287904346ca71cffb303b095fdea4d101972c4452bec37de57d6ca3/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "4b9250cc81ab",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HTTPD_PREFIX=/usr/local/apache2",
"HTTPD_VERSION=2.4.52",
"HTTPD_SHA256=0127f7dc497e9983e9c51474bed75e45607f2f870a7675a86dc90af6d572f5c9",
"HTTPD_PATCHES="
],
"Cmd": [
"/bin/sh"
],
"Image": "httpd",
"Volumes": null,
"WorkingDir": "/usr/local/apache2",
"Entrypoint": null,
"OnBuild": null,
"Labels": {},
"StopSignal": "SIGWINCH"
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "4f872c84c4554658d339b929da6680defeee2165d9372b8dbb599e4ea68d1176",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"80/tcp": null
},
"SandboxKey": "/var/run/docker/netns/4f872c84c455",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "178500a2ccfc5400ce8ad199a613a4c05eddb54ab6b1ee3ae298fa0157b72e5d",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "b82f93cad3d44f7dc1e4b203b53b06aeafc3b0fd1b086cdd05e7ea50ef1a8f43",
"EndpointID": "178500a2ccfc5400ce8ad199a613a4c05eddb54ab6b1ee3ae298fa0157b72e5d",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
存储驱动
docker提供了多种存储驱动来实现不同的方式存储镜像,下面是常用的几种存储驱动:
- AUFS
- OverlayFS
- Devicemapper
- Btrfs
- VFS
AUFS
AUFS(AnotherUnionFS)是一种Union FS,是文件级的存储驱动。AUFS是一个能透明覆盖一个或多个现有文件系统的层状文件系统,把多层合并成文件系统的单层表示。简单来说就是支持将不同目录挂载到同一个虚拟文件系统下的文件系统。这种文件系统可以一层一层地叠加修改文件。无论底下有多少层都是只读的,只有最上层的文件系统是可写的。当需要修改一个文件时,AUFS创建该文件的一个副本,使用CoW将文件从只读层复制到可写层进行修改,结果也保存在可写层。在Docker中,底下的只读层就是image,可写层就是Container。
AUFS文件系统据说有3W行代码,而ext4文件系统却只有4000-5000行左右代码,这些代码是要被整合进内核的,后来AUFS申请要被合并进内核代码的时候,linuz觉得它这代码太过臃肿,于是拒绝了。因此AUFS这个文件系统一直以来就不是linux内核中自有的文件系统,想用AUFS这个文件系统的话,必须自己向内核打补丁并去编译使用它,但redhat系列的操作系统一向以稳定著称,不会干这种出格的事,所以在redhat系列操作系统中使用AUFS并无可能。而ubuntu上的docker默认使用的就是AUFS。
OverlayFS
Overlay是Linux内核3.18后支持的,也是一种Union FS,和AUFS的多层不同的是Overlay只有两层:一个upper文件系统和一个lower文件系统,分别代表Docker的镜像层和容器层。当需要修改一个文件时,使用CoW将文件从只读的lower复制到可写的upper进行修改,结果也保存在upper层。在Docker中,底下的只读层就是image,可写层就是Container。目前最新的OverlayFS为Overlay2。
AUFS和Overlay都是联合文件系统,但AUFS有多层,而Overlay只有两层,所以在做写时复制操作时,如果文件比较大且存在比较低的层,则AUSF会慢一些。而且Overlay并入了linux kernel mainline,AUFS没有。目前AUFS已基本被淘汰。
DeviceMapper
Device mapper是Linux内核2.6.9后支持的,提供的一种从逻辑设备到物理设备的映射框架机制,在该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略。AUFS和OverlayFS都是文件级存储,而Device mapper是块级存储,所有的操作都是直接对块进行操作,而不是文件。Device mapper驱动会先在块设备上创建一个资源池,然后在资源池上创建一个带有文件系统的基本设备,所有镜像都是这个基本设备的快照,而容器则是镜像的快照。所以在容器里看到文件系统是资源池上基本设备的文件系统的快照,并没有为容器分配空间。当要写入一个新文件时,在容器的镜像内为其分配新的块并写入数据,这个叫用时分配。当要修改已有文件时,再使用CoW为容器快照分配块空间,将要修改的数据复制到在容器快照中新的块里再进行修改。
OverlayFS是文件级存储,Device mapper是块级存储,当文件特别大而修改的内容很小,Overlay不管修改的内容大小都会复制整个文件,对大文件进行修改显然要比小文件要消耗更多的时间,而块级无论是大文件还是小文件都只复制需要修改的块,并不是整个文件,在这种场景下,显然device mapper要快一些。因为块级的是直接访问逻辑盘,适合IO密集的场景。而对于程序内部复杂,大并发但少IO的场景,Overlay的性能相对要强一些。
BTRFS
由Oracle于2007年宣布并进行中的COW(copy-on-write式)文件系统。目标是取代Linuxext3文件系统,改善ext3的限制,特别是单一文件大小的限制,总文件系统大小限制以及加入文件校验和特性。加入ext3/4未支持的一些功能,例如可写的磁盘快照(snapshots),以及支持递归的快照(snapshots of snapshots),内建磁盘阵列(RAID)支持,支持子卷(Subvolumes)的概念,允许在线调整文件系统大小。
Linux 有丰富的文件系统可供选择,但是我们面临着许多挑战,即扩展到大型存储子系统,这些子系统在当今的数据中心中变得越来越普遍。文件系统需要扩展其寻址和管理大型存储的能力,以及检测、修复和容忍磁盘上存储的数据中的错误的能力。
VFS
虚拟文件系统(Virtual File System,简称VFS)是Linux内核的子系统之一,它为用户程序提供文件和文件系统操作的统一接口,屏蔽不同文件系统的差异和操作细节。借助VFS可以直接使用open()
、read()
、write()
这样的系统调用操作文件,而无须考虑具体的文件系统和实际的存储介质。
VFS的作用就是采用标准的Unix系统调用读写位于不同物理介质上的不同文件系统,即为各类文件系统提供了一个统一的操作界面和应用编程接口。VFS是一个可以让open()、read()、write()等系统调用不用关心底层的存储介质和文件系统类型就可以工作的粘合层。
VFS使得Linux可以支持多个不同的文件系统,每个表示一个VFS 的通用接口。 由于软件将Linux 文件系统的所有细节进行了转换,所以Linux核心的其它部分及系统中运行的程序将看到统一的文件系统。 Linux 的虚拟文件系统允许用户同时能透明地安装许多不同的文件系统。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义