文章目录
docker的发展史
LXC
通过传统方式使用容器功能的话需要我们自己写代码去进行系统调用来实现创建内核,实际上拥有此能力的人廖廖无几。而LXC(LinuX Container)把容器技术做得更加易用,把需要用到的容器功能做成一组工具,从而极大的简化用户使用容器技术的麻烦程度。
LXC是最早一批真正把完整的容器技术用一组简易使用的工具和模板来极大的简化了容器技术使用的一个方案。
LXC虽然极大的简化了容器技术的使用,但比起直接通过内核调用来使用容器技术,其复杂程度其实并没有多大降低,因为我们必须要学会LXC的一组命令工具,且由于内核的创建都是通过命令来实现的,通过批量命令实现数据迁移并不容易。其隔离性也没有虚拟机那么强大。
后来就出现了docker,所以从一定程度上来说,docker就是LXC的增强版。
docker基本概念
docker是容器技术的一个前端工具,容器是内核的一项技术,docker只是把这一项技术的使用得以简化,使之普及而已。
LXC进行大规模创建容器很难,想在另一台主机上复刻一个一模一样的容器也很难,而docker就是从这方面着手去找解决方案。所以docker早期的版本其核心就是一个LXC,docker对其进行了二次封装,功能的实现是通过LXC做容器管理引擎,但是在创建容器时,不再是像LXC一样用模板去现场安装,而是事先通过一种类似镜像技术,就像在KVM中一样,将一个操作系统打包成一个镜像,然后将这个镜像拷贝到目标主机上直接部署启动。
我们可以尝试着把一个操作系统用户空间需要用到的所有组件,事先准备、编排好,编排好以后整体打包成一个文件,这个文件我们称其为镜像文件(image)。
docker的镜像文件是放在一个集中统一的互联网仓库中的,把一些人们常用的镜像文件放在互联网仓库中,比如最小化的centos系统,有时我们需要在操作系统上安装一些应用,比如nginx,我们就可以在一个最小化的centos系统中安装一个nginx,然后将其打包成镜像,将其放在互联网仓库中,当人们想启动一个容器的时候,docker会到这个互联网仓库中去下载我们需要的镜像到本地,并基于镜像来启动容器。
自docker 0.9版本起,docker除了继续支持LXC外,还开始引入自家的libcontainer,试图打造更通用的底层容器虚拟化库。如今的docker基本上都已经是使用libcontainer而非LXC了。
从操作系统功能上看,docker底层依赖的核心技术主要包括Linux操作系统的命名空间、控制组、联合文件系统和Linux虚拟网络支持。
docker基础用法
什么是docker
docker中的容器:
- lxc --> libcontainer --> runC
OCI&OCF
OCI
Open Container-initiative(开放容器倡议)
- 由Linux基金会主导于2015年6月创立
- 旨在围绕容器格式和运行时制定一个开放的工业化标准
- 包含两种规格
- 运行时规范(运行时规范)
- 图像规范(图像规范)
OCF
Open Container Format(开放容器格式)
runC 是一个 CLI 工具,用于根据 OCI 规范生成和运行容器
- 容器作为 runC 的子进程启动,可以嵌入到各种其他系统中,而无需运行守护程序
- runC 建立在 libcontainer 之上,同样的容器技术为数百万个 Docker 引擎安装提供支持
docker提供了一个专门容纳容器镜像的站点:https://hub.docker.com
docker架构
docker镜像与镜像仓库
镜像是静态的,而容器是动态的,容器有其生命周期,镜像与容器的关系类似于程序与进程的关系。镜像类似于文件系统中的程序文件,而容器则类似于将一个程序运行起来的状态,也即进程。所以容器是可以删除的,容器被删除后其镜像是不会被删除的。
docker对象
使用 Docker 时,您正在创建和使用映像、容器、网络、卷、插件和其他对象。
- IMAGES(图像)
- 映像是一个只读模板,其中包含有关创建 docker 容器的说明。
- 通常,一个映像基于另一个映像,并具有一些额外的自定义。
- 您可以创建自己的映像,也可以仅使用其他人创建并在注册表中发布的映像。
- CONTAINERS(器皿)
- 控制器是映像的可运行实例。
- 您可以使用 Docker API 或 CLI 创建、运行、停止、移动或删除容器。
- 可以将容器连接到一个或多个网络,将存储附加到该容器,甚至可以基于其当前状态创建新映像。
安装及使用docker
docker安装
[root@cl ~]# cd /etc/yum.repos.d/
[root@cl yum.repos.d]# curl -o docker-ce.repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--100 1919 100 1919 0 0 8722 0 --:--:-- --:--:-- --:--:-- 8722
[root@cl yum.repos.d]# sed -i 's@https://download.docker.com@https://mirrors.tuna.tsinghua.edu.cn/docker-ce@g' docker-ce.repo
[root@cl yum.repos.d]# yum -y install docker-ce
docker加速
[root@cl ~]# mkdir -p /etc/docker
[root@cl ~]# tee /etc/docker/daemon.json <<-'EOF'
> {
> "registry-mirrors": ["https://sdj8kwlf.mirror.aliyuncs.com"]
> }
> EOF
{
"registry-mirrors": ["https://sdj8kwlf.mirror.aliyuncs.com"]
}
[root@cl ~]# systemctl daemon-reload
[root@cl ~]# systemctl restart docker
docker常用操作
命令 | 功能 |
---|---|
docker search | 在 Docker 中心搜索映像 |
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 对象的低级信息 |
//docker search //搜索镜像
[root@cl ~]# docker search httpd
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
httpd The Apache HTTP Server Project 4106 [OK]
centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui?? 44
centos/httpd 35 [OK]
clearlinux/httpd httpd HyperText Transfer Protocol (HTTP) ser?? 2
hypoport/httpd-cgi httpd-cgi 2 [OK]
......
//docker pull //拉取镜像
[root@cl ~]# 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@cl ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest dabbfbe0c57b 7 months ago 144MB
//docker create //基于镜像创建容器
[root@cl ~]# docker create -it --name web httpd /bin/bash
f138eceb22b930e378866643bb6e8be64d996e12e5b727e32babbda113fc50f5
//docker start //启动容器
[root@cl ~]# docker start f138eceb22b9
f138eceb22b9
//docker run //启动并进入容器
//-it 使用交互方式运行,进入容器查看内容
[root@cl ~]# docker run -it httpd /bin/bash
root@9dcd2e364b05:/usr/local/apache2#
//docker attach //连接到正在运行中的容器
[root@cl ~]# docker restart f138eceb22b9
f138eceb22b9
[root@cl ~]# docker attach f138eceb22b9
root@f138eceb22b9:/usr/local/apache2#
//docker ps //列出正在运行的容器
-a //列出所有的容器
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@cl ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9dcd2e364b05 httpd "/bin/bash" 8 minutes ago Exited (0) 6 minutes ago naughty_mirzakhani
f138eceb22b9 httpd "/bin/bash" 10 minutes ago Exited (0) 7 seconds ago web
//docker logs //输出当前容器日志信息
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f138eceb22b9 httpd "/bin/bash" 12 minutes ago Up 41 seconds 80/tcp web
[root@cl ~]# docker logs f138eceb22b9
root@f138eceb22b9:/usr/local/apache2# root@f138eceb22b9:/usr/local/apach
root@f138eceb22b9:/usr/local/apache2# exit
exit
//docker restart //重启容器
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f138eceb22b9 httpd "/bin/bash" 13 minutes ago Up About a minute 80/tcp web
[root@cl ~]# docker restart f138eceb22b9
f138eceb22b9
//docker stop //停止容器
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f138eceb22b9 httpd "/bin/bash" 14 minutes ago Up 26 seconds 80/tcp web
[root@cl ~]# docker stop f138eceb22b9
f138eceb22b9
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//docker kill //强制停止当前容器
[root@cl ~]# docker restart 9dcd2e364b05
9dcd2e364b05
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9dcd2e364b05 httpd "/bin/bash" 16 minutes ago Up 4 seconds 80/tcp naughty_mirzakhani
[root@cl ~]# docker kill 9dcd2e364b05
9dcd2e364b05
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//docker rm //删除容器
[root@cl ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9dcd2e364b05 httpd "/bin/bash" 17 minutes ago Exited (137) 48 seconds ago naughty_mirzakhani
f138eceb22b9 httpd "/bin/bash" 20 minutes ago Exited (137) 5 minutes ago web
[root@cl ~]# docker rm 9dcd2e364b05
9dcd2e364b05
[root@cl ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f138eceb22b9 httpd "/bin/bash" 20 minutes ago Exited (137) 5 minutes ago web
//docker rm -f $(docker ps -aq) //删除所有的容器
[root@cl ~]# docker rm -f $(docker ps -qa)
f138eceb22b9
[root@cl ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//docker exec //进入容器后开启一个新的终端 (可以在里面操作)
[root@cl ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5218d47f12b1 httpd "/bin/bash" About a minute ago Exited (0) About a minute ago affectionate_bhaskara
673057f6a90f httpd "httpd-foreground" 7 minutes ago Exited (0) 7 minutes ago web
[root@cl ~]# docker start 5218d47f12b1
5218d47f12b1
[root@cl ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5218d47f12b1 httpd "/bin/bash" 2 minutes ago Up 4 seconds 80/tcp affectionate_bhaskara
[root@cl ~]# docker exec -it 5218d47f12b1 /bin/bash
root@5218d47f12b1:/usr/local/apache2#
//docker info //显示系统相关信息
[root@cl ~]# 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: 2
Running: 1
Paused: 0
Stopped: 1
Images: 1
Server Version: 20.10.17
Storage Driver: overlay2
Backing Filesystem: xfs
......
//docker inspect //查看镜像的元数据
[root@cl ~]# docker inspect httpd
[
{
"Id": "sha256:dabbfbe0c57b6e5cd4bc089818d3f664acfad496dc741c9a501e72d15e803b34",
"RepoTags": [
"httpd:latest"
],
"RepoDigests": [
"httpd@sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32"
],
"Parent": "",
"Comment": "",
"Created": "2021-12-21T01:36:12.729599368Z",
"Container": "2e3825874c832964f871068b149d74ac708e0968257683b2177adc127faf9b4e",
"ContainerConfig": {
"Hostname": "2e3825874c83",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
......
docker event state
docker存储驱动
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
Btrfs是下一代的copy-on-write文件系统,它支持很多高级特性,使其更加适合Docker。Btrfs合并在内核主线中,并且它的on-disk-format也逐渐稳定了。不过,它的很多特性还仍然处于开发中。
Docker的btrfs存储驱动利用了很多Btrfs特性来管理镜像和容器。这些特性中最重要的就是thin provisioning(超配)、copy-on-write和快照。
Btrfs一直被认为是Linux文件系统的未来。在Linux内核主线的全力支持下,稳定的on-disk-format,关注于稳定性的积极开发,使得Btrfs逐渐成为现实。
只要Docker还在Linux平台上运行,人们就会认为btrfs存储驱动会替代devicemapper存储驱动,成为潜在的长期的存储驱动。然而,在写耗时上,devicemapper被认为更安全,更稳定,更适合商品化。只有当你很了解Btrfs,并且有丰富的经验时,才可以考虑btrfs驱动商品化。
VFS
vfs是接口的“原生”的实现,完全没有使用联合文件系统或者写时复制技术,而是将所有的分层依次拷贝到静态的子文件夹中,然后将最终结果挂载到容器的根文件系统。它并不适合实际或者生产环境使用,但是对于需要进行简单验证的场景,或者需要测试Docker引擎的其他部件的场景,是很有价值的。