Docker学习笔记-入门篇
文章目录
- Docker概述
- Docker为什么会出现
- Docker的历史
- Docker为什么这么火(有什么优势)
- Docker是什么
- Docker能做什么
- Docker的基本组成
- Docker为什么比虚拟机快
- Docker安装、卸载
- 1、Centos7
- 配置阿里云的容器镜像加速器
- 回顾启动hello-world镜像的流程
- Docker常用命令
- 帮助命令
- 镜像命令
- docker images
- docker search
- docker pull
- docker rmi
- docker history
- docker save/load
- 容器命令
- docker run
- docker ps
- docker rm
- docker start/stop/restart/kill
- docker exec
- docker attach
- 常用的其它命令
- docker logs
- docker top
- docker inspect
- docker cp
- docker stats
- docker命令小结
- 作业
- 练习1
- 可视化
- Docker镜像
- 镜像是什么
- Docker镜像的加载原理
- UnionFS(联合文件系统)
- Docker镜像加载原理
- 分层理解
- commit镜像
- 练习
Docker概述
Docker为什么会出现
来看以下场景:
- 如果在公司做过开发的童鞋就会知道,一个项目有开发/测试环境,和线上环境。而每套环境都需要部署应用环境,对应用进行配置。
- 程序在开发环境可以使用,在线上环境不可用。又或者线上环境由于服务器操作系统其他组件的更新,导致该项目的服务不可用。这对于运维来说,考验很大。
- 环境配置是十分麻烦的,每台机器都要部署环境(集群redis、ES、hadoop),费时费力。
之前在服务器上配置一个应用的环境(Redis MySQL ES JDK Hadoop),非常麻烦,而且环境是不跨平台的。比方说下面的场景:
传统:开发人员将项目打包成jar,然后将其交给运维来部署;
如今:开发+打包+部署,一套流程做完。
所以,能否发布一个项目(比如springboot fat jar + (Redis MySQL JDK ES Hadoop)),连同环境一起打包? Docker就是做这个事情的。
java --> jar --> 打包项目且带上环境(docker镜像)–> Docker仓库 --> 下载我们发布的镜像 --> 直接运行即可!
技术的本质:所有的技术的出现都是因为有新问题需要解决。也因此我们才需要去学习。
Docker的历史
2010年,几个搞IT的年轻人,在美国成立了一家公司dotCloud。
做一些PaaS的云计算服务,LXC的容器技术。
他们将自己的技术(容器化技术)命名就是Docker。
Docker刚刚诞生的时候并没有引起行业的注意。所以为了让公司存活下去,于是把Docker开源了。
后来,越来越多的人发现了docker的优点,开始火了起来。Docker每个月都会更新一个版本。2014年4月9日,Docker 1.0发布。
Docker为什么这么火(有什么优势)
- 很轻巧
容器出现前,普遍用的是虚拟机,比如常见的VMware。虚拟机很笨重。
- 应用可以更快的交付和部署
传统方式:一堆帮助文档,安装程序;
docker:打包镜像,发布测试,一键运行。
- 扩容和缩容更便捷
使用了docker之后,我们部署应用就像搭积木一样简单。
- 更简单的系统运维
在容器化之后,我们的开发、测试环境都是高度一致的。
- 更高效的计算资源利用
一个物理机上可以运行很多个容器实例。
Docker是什么
引用维基百科对Docker的介绍:
Docker是Go语言开发的开源项目。
官方文档:https://docs.docker.com 。文档很详细!
官方镜像仓库:https://hub.docker.com
Docker能做什么
- 容器化技术与虚拟机技术的区别
容器化技术不是模拟一个完整的操作系统;
容器内的应用直接运行在宿主机上,容器是没有自己的内核的,也没有虚拟出硬件;
每个容器间相互隔离,每个容器内都有属于自己的一个文件系统。
Docker的基本组成
Docker是一个C/S架构的系统,Docker的守护进程运行在主机上。客户端通过socket去访问服务端。
Docker为什么比虚拟机快
1、Docker有着比虚拟机更少的抽象层;
2、Docker使用的是宿主机的内核,而VM使用的是虚拟出来的Guest OS。
因此,新建一个容器时,docker不需要像虚拟机一样重新加载一个操作系统内核,能够做到秒级的加载速度;而虚拟机是加载Guest OS,分钟级别的加载速度。
- 镜像(image)
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务。一个镜像可以创建多个容器(container)。
- 容器(container)
Docker利用容器技术,独立运行一个或者一个组应用。
目前可以把这个容器理解为一个简易的Linux系统。
- 仓库(repository)
用来存放镜像的地方。
仓库分为公有仓库和私有仓库。
Docker安装、卸载
从官方文档获取安装方法。
1、Centos7
1、先卸载旧版本的docker
$ sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
2、设置镜像的仓库
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo // 将上面官方的仓库改为国内的镜像仓库地址:
$ sudo yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo// 更新yum源或者出现配置yum源之后,通常都会使用yum makecache 生成缓存,
// 这个命令是将软件包信息提前在本地缓存一份,用来提高搜索安装软件的速度。
$ sudo yum makecache fast// 如果觉得占用磁盘空间,可以使用yum clean指令清除缓存。
$ sudo yum clean all
3、安装docker引擎
// 直接安装最新版本
$ sudo yum install docker-ce docker-ce-cli containerd.io//查看可安装的docker版本
$ yum list docker-ce --showduplicates | sort -r
//安装指定版本的docker
$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
4、启动docker服务
$ sudo systemctl start docker
使用docker version
来判断是否安装成功:
或运行官方的hello-world
镜像来验证。
$ sudo docker run hello-world
5、Docker的卸载
- Step1:Uninstall the Docker Engine, CLI, and Containerd packages:
$ sudo yum remove docker-ce docker-ce-cli containerd.io
- Step2:Images, containers, volumes, or customized configuration files on your host are not automatically removed. To delete all images, containers, and volumes:
$ sudo rm -rf /var/lib/docker
$ sudo rm -rf /var/lib/containerd
6、其实可以指定镜像、容器存放的位置。
编辑/etc/docker/daemon.json
文件即可(如果不存在该文件,则新建)。
配置阿里云的容器镜像加速器
同样是编辑 /etc/docker/daemon.json
文件即可。
PS:每个阿里云用户的加速地址都不同的。上面这个我记得当时我是在网络上找的别人的加速地址。
另外,其实腾讯云也有这种加速服务的。
回顾启动hello-world镜像的流程
docker run
命令的执行流程如下图:
Docker常用命令
官方参考文档:https://docs.docker.com/reference/
帮助命令
docker version //显示版本信息
docker info //显示docker的系统信息,包括镜像和容器
docker <COMMAND> --help //万能命令
镜像命令
docker images
查看所有本机的镜像
[root@VM-8-8-centos ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 6 months ago 13.3kB//解释
REPOSITORY 镜像在仓库中的名称
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小 //可选项
Options:-a, --all Show all images (default hides intermediate images)-q, --quiet Only show image IDs
docker search
搜索镜像
[root@VM-8-8-centos ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11433 [OK]
mariadb MariaDB Server is a high performing open sou… 4341 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 848 [OK]
percona Percona Server is a fork of the MySQL relati… 554 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 324 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 91
mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 88
centurylink/mysql Image containing mysql. Optimized to be link… 59 [OK]//可选项
Options:-f, --filter filter //过滤出符合指定条件的结果//过滤出STARS>=3000的mysql镜像
[root@VM-8-8-centos ~]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11433 [OK]
mariadb MariaDB Server is a high performing open sou… 4341 [OK]
docker pull
拉取镜像
docker pull 镜像名[:tag]
[root@VM-8-8-centos ~]# docker pull mysql
Using default tag: latest //如果不指定tag,默认就是lastest
latest: Pulling from library/mysql
a330b6cecb98: Pull complete //分层下载, docker images 的核心
9c8f656c32b8: Pull complete
88e473c3f553: Pull complete
062463ea5d2f: Pull complete
daf7e3bdf4b6: Pull complete
1839c0b7aac9: Pull complete
cf0a0cfee6d0: Pull complete
1b42041bb11e: Pull complete
10459d86c7e6: Pull complete
b7199599d5f9: Pull complete
1d6f51e17d45: Pull complete
50e0789bacad: Pull complete
Digest: sha256:99e0989e7e3797cfbdb8d51a19d32c8d286dd8862794d01a547651a896bcf00c //签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest //真实地址,换言之:docker pull mysql 等价于 docker pull docker.io/library/mysql:latest
docker rmi
删除镜像
//删除单个容器
[root@VM-8-8-centos ~]# docker rmi -f <images id>//删除多个容器
[root@VM-8-8-centos ~]# docker rmi -f <images id1> <images id2> <images id3> ...//删除所有镜像
[root@VM-8-8-centos ~]# docker rmi -f $(docker images -aq)// 解释:
-f 表示强制删除
docker images -aq 得到所有的镜像ID
docker history
查看镜像的构建过程(即镜像的历史变更记录)
docker history <镜像ID>
docker save/load
docker save
用于将镜像备份到一个tar包
docker load
用于从指定tar包中还原镜像
[root@VM-8-8-centos ~]# docker save --helpUsage: docker save [OPTIONS] IMAGE [IMAGE...]Save one or more images to a tar archive (streamed to STDOUT by default)Options:-o, --output string Write to a file, instead of STDOUT[root@VM-8-8-centos ~]# docker load --helpUsage: docker load [OPTIONS]Load an image from a tar archive or STDINOptions:-i, --input string Read from tar archive file, instead of STDIN-q, --quiet Suppress the load output
docker save
备份镜像:
docker load
还原镜像:
容器命令
先拉取容器,这里以centos:latest
镜像为例。
docker run
启动指定容器
docker run [可选参数] <image>常用的可选参数说明:
--name="container name" //给容器起名字,用来区分容器
-d //后台方式运行
-it //使用交互式方式启动,可进入容器查看
-p //指定端口,也可作主机和容器的端口映射。// e.g: -p ip:主机端口:容器端口-p 主机端口:容器端口-p 容器端口
-P //随机指定端口
--rm //用完即删 Automatically remove the container when it exits
docker ps
列出容器
docker ps [可选参数]常用的可选参数说明:
-a //列出所有的容器,如果不加该参数,则只显示运行中的容器
-n int //列出最近创建的int个容器
-q //只显示容器ID[root@VM-8-8-centos ~]# docker ps -n 1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be3b2ad39f46 centos:7.6.1810 "/bin/bash" 10 seconds ago Up 10 seconds centos_7.6[root@VM-8-8-centos ~]# docker ps -n 2
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be3b2ad39f46 centos:7.6.1810 "/bin/bash" 13 seconds ago Up 12 seconds centos_7.6
5ff746ad9c8a centos:latest "/bin/bash" About a minute ago Up About a minute centos_8
docker rm
删除指定容器
docker rm <容器ID> //删除指定容器,不能
docker rm -f $(docker ps -aq) //删除所有容器
docker ps -aq |xargs docker rm //也是删除所有容器
docker start/stop/restart/kill
启动、停止、重启和强制停止容器
docker start <容器id> //启动容器
docker stop <容器id> //停止容器
docker restart <容器id> //重启容器
docker kill <容器id> //强制停止容器
docker exec
在运行的容器中执行一条命令
可选命令:
Options:-d, --detach Detached mode: run command in the background--detach-keys string Override the key sequence for detaching a container-e, --env list Set environment variables--env-file list Read in a file of environment variables-i, --interactive Keep STDIN open even if not attached--privileged Give extended privileges to the command-t, --tty Allocate a pseudo-TTY-u, --user string Username or UID (format: <name|uid>[:<group|gid>])-w, --workdir string Working directory inside the container//示例
// 进入容器的交互式bash shell
$ sudo docker exec -it <容器id> /bin/bash
// 以root用户进入容器的交互式bash shell
$ sudo docker exec -u 0 -it <容器id> /bin/bash
docker attach
进入正在运行的容器。
与docker exec -it <容器id> /bin/bash 的区别:不会进入一个新的shell,而是当前容器运行用的shell。
docker attach <容器id>
常用的其它命令
docker logs
查看日志
Options:--details Show extra details provided to logs-f, --follow Follow log output--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative(e.g. 42m for 42 minutes)-n, --tail string Number of lines to show from the end of the logs (default "all")-t, --timestamps Show timestamps--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative(e.g. 42m for 42 minutes)//示例:
[root@VM-8-8-centos ~]# docker logs -ft -n 1 centos_7.6
2021-09-20T01:39:07.127995518Z [root@be3b2ad39f46 /]#
docker top
查看容器中的进程信息
$ sudo docker top <容器id>
[root@VM-8-8-centos ~]# docker top be3b2ad39f46
UID PID PPID C STIME TTY TIME CMD
root 4398 4379 0 Sep20 pts/0 00:00:00 /bin/bash
docker inspect
查看容器的元数据
$ sudo docker inspect <容器id>[root@VM-8-8-centos ~]# docker inspect 5ff746ad9c8a
[{"Id": "5ff746ad9c8a8e3642eb39e1d520003dbb7ac7141538484ddfa5d8cf83446273","Created": "2021-09-20T01:35:08.558366371Z","Path": "/bin/bash","Args": [],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 2939,"ExitCode": 0,"Error": "","StartedAt": "2021-09-20T01:35:08.791459407Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6","ResolvConfPath": "/var/lib/docker/containers/5ff746ad9c8a8e3642eb39e1d520003dbb7ac7141538484ddfa5d8cf83446273/resolv.conf","HostnamePath": "/var/lib/docker/containers/5ff746ad9c8a8e3642eb39e1d520003dbb7ac7141538484ddfa5d8cf83446273/hostname","HostsPath": "/var/lib/docker/containers/5ff746ad9c8a8e3642eb39e1d520003dbb7ac7141538484ddfa5d8cf83446273/hosts","LogPath": "/var/lib/docker/containers/5ff746ad9c8a8e3642eb39e1d520003dbb7ac7141538484ddfa5d8cf83446273/5ff746ad9c8a8e3642eb39e1d520003dbb7ac7141538484ddfa5d8cf83446273-json.log","Name": "/centos_8","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "","ExecIDs": ["196c4752f03e46c92a9f456c3c495a69653d8ef7221a603e6ffd71afd13459dc"],"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/d29ea0e0ca0e9ab291d52b3b53416a7f057b719c792256c216d418681ec30bf1-init/diff:/var/lib/docker/overlay2/24b5f032294785128522bd7e768bcc6d43829e8dc659ca2c49c70c94ace55d55/diff","MergedDir": "/var/lib/docker/overlay2/d29ea0e0ca0e9ab291d52b3b53416a7f057b719c792256c216d418681ec30bf1/merged","UpperDir": "/var/lib/docker/overlay2/d29ea0e0ca0e9ab291d52b3b53416a7f057b719c792256c216d418681ec30bf1/diff","WorkDir": "/var/lib/docker/overlay2/d29ea0e0ca0e9ab291d52b3b53416a7f057b719c792256c216d418681ec30bf1/work"},"Name": "overlay2"},"Mounts": [],"Config": {"Hostname": "5ff746ad9c8a","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"Tty": true,"OpenStdin": true,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/bash"],"Image": "centos:latest","Volumes": null,"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {"org.label-schema.build-date": "20210915","org.label-schema.license": "GPLv2","org.label-schema.name": "CentOS Base Image","org.label-schema.schema-version": "1.0","org.label-schema.vendor": "CentOS"}},"NetworkSettings": {"Bridge": "","SandboxID": "7a2f54144ca594acbe782cbb3e88eb7459124bdad2276c9d5721a9881526ec1f","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/7a2f54144ca5","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "623ad66a1c64559d4149081b14b5408f54660e683daa5da5b1cc4f49cb824928","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": "c3710726a487a0ce29f841cdbcc6eea5eda5a66e10fa85e8b6db3775ca8849d9","EndpointID": "623ad66a1c64559d4149081b14b5408f54660e683daa5da5b1cc4f49cb824928","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 cp
在容器和本地文件系统之间拷贝文件/目录
//从主机往容器里拷贝文件
docker cp bbb.txt be3b2ad39f46:/tmp///从容器往主机拷贝文件
docker cp be3b2ad39f46:/tmp/ks-script-6pKh_p /root
PS: 后面我们可以使用 -v (容器数据卷的技术)来实现容器目录和主机目录的自动同步。
docker stats
查看容器的cpu、内存等使用状态
docker stats //查看所有容器的cpu、内存等使用状态
docker stats <容器id> //查看指定容器的cpu、内存等使用状态
docker命令小结
前面主要讨论了容器、镜像相关的一些命令,还有很多命令在后面一些知识点会讲到,比如跟远程仓库、Dockerfile相关的…
作业
练习1
部署elasticsearch + kibana
按照官方文档(https://hub.docker.com/_/elasticsearch)下载并启动elasticsearch:
[root@VM-8-8-centos ~]# docker run -itd --name elasticsearch_v7.6.2 -p 19200:9200 -p 19300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
由于ES启动后会占用大量内存,docker stats
查看结果如下:
这对于1核CPU-2GB内存的云服务器来说(主要是穷o(╥﹏╥)o)负担较重。因此使用-e
参数传入ES的环境变量ES_JAVA_OPTS
来控制内存的使用量:
[root@VM-8-8-centos ~]# docker run -itd --name elasticsearch_v7.6.2 -p 19200:9200 -p 19300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
这下ES的内存占用就变小了:
部署好ES后,部署kibana。
思考:如何使用kibana连接es?
可视化
- Portainer
- Rancher
Docker镜像
镜像是什么
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包成docker镜像,就可以直接跑起来。
如何得到镜像?
- 从远程仓库下载
- 其他人拷贝给你
- 自己制作一个镜像Dockfile
Docker镜像的加载原理
UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的的文件系统。它支持对文件系统的修改作为一次提交来一层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
docker镜像实际上是由一层一层的文件系统组成,这种层级的文件系统叫UnionFS。
bootfs(boot file system) 主要包含bootloader和kernel,bootloader主要是引导并加载kernel。Linux刚启动时会加载bootfs文件系统。在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含bootloader和kernel。当bootloader加载完kernel后,kernel就在内存中了。此时内存的使用权就由bootfs交由kernel。
而rootfs(root file system)在 bootfs之上,包含的就是Linux系统中的/dev
,/proc
,/bin
,/etc
等标准目录和文件。rootfs就是各种不同的linux系统发行版,比如Ubuntu、OpenSUSE、CentOS等。
平时我们安装的到虚拟机的CentOS都是好几个G,为什么Docker里才200+M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了。因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。
分层理解
在通过docker pull
下载镜像时,可以观察下载时的日志输出。可以看到是一层一层下载的,如下图:
所有的Docker镜像都是始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层上,创建新的镜像层。
举一个简单的例子,例如基于Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已包含3个镜像层,如下图(这只是一个简单的例子):
在添加额外镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图又是一个简单的例子:每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层级跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层的文件7是文件5个一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和Copy on Write。
- 特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就是我们常说的容器层,容器层之下都叫镜像层。
commit镜像
docker commit //提交当前容器,成为一个新的副本docker commit -m="提交的描述信息" -a="作者" <容器id> 目标镜像名:[TAG]
练习
启动一个官方的tomcat容器。发现这个tomcat容器的
/usr/local/tomcat/webapps
目录是空的。往该目录拷贝文件后,再提交镜像。
[root@VM-8-8-centos ~]# docker commit -m "copy webapps.dist to webapps" -a "cloud-hacker" 1466e04bc744 tomcat9:v1.0
sha256:c5673696fcfadd7a7dffc41bf7959295116dd1fbeb17e679aff63d6ad7d82cc6
[root@VM-8-8-centos ~]#
commit后,docker images
查看本地镜像便能看到它。
综上,如果想要保存当前容器状态,就可以通过
docker commit
来提交获得一个镜像。
这就类似于虚拟机的快照。
学到这里,才算是入门了Docker!
学习方式说明:
理解概念(一开始可以不需要理解有多深入,可以模棱两可),然后一定要实践,最后实践+理论相结合一次搞定这个知识!
Docker学习笔记-入门篇相关推荐
- Vue学习笔记入门篇——数据及DOM
本文为转载,原文:Vue学习笔记入门篇--数据及DOM 数据 data 类型 Object | Function 详细 Vue 实例的数据对象.Vue 将会递归将 data 的属性转换为 getter ...
- C# 学习笔记入门篇(上)
文章目录 C# 学习笔记入门篇 〇.写在前面 Hello World! 这篇学习笔记适合什么人 这篇学习笔记到底想记什么 附加说明 一.命名空间 "进入"命名空间 嵌套的命名空间. ...
- R语言学习笔记——入门篇:第一章-R语言介绍
R语言 R语言学习笔记--入门篇:第一章-R语言介绍 文章目录 R语言 一.R语言简介 1.1.R语言的应用方向 1.2.R语言的特点 二.R软件的安装 2.1.Windows/Mac 2.2.Lin ...
- R语言学习笔记——入门篇:第三章-图形初阶
R语言 R语言学习笔记--入门篇:第三章-图形初阶 文章目录 R语言 一.使用图形 1.1.基础绘图函数:plot( ) 1.2.图形控制函数:dev( ) 补充--直方图函数:hist( ) 补充- ...
- 易语言学习笔记——入门篇
易语言学习笔记20180709 最早接触易语言是三年前的事情了,那时候是因为DNF这个游戏我才知道了易语言这个编程语言,当时对他就非常的憧憬.只不过那时候易语言的学习资源比较少,而且自身的学业比较重就 ...
- zabbix学习笔记——入门篇
目录 一.了解监控 监控的种类 二.zabbix监控 1.介绍zabbix 2.为什么选择zabbix 3.Zabbix可监控对象 4.zabbix监控方式 1.被动监控 2.主动监控 5.zabbi ...
- JavaScript学习笔记 - 入门篇(1)- 准备
为什么学习JavaScript 一.你知道,为什么JavaScript非常值得我们学习吗? 所有主流浏览器都支持JavaScript. 目前,全世界大部分网页都使用JavaScript. 它可以让网页 ...
- GeneXus学习笔记——入门篇
使用GeneXus做开发做了有一段时间了 却发现一个问题(O_O)?就是除了相关的Wiki外 网上其他地方的相关资料都很少 于是乎我就想在这记录一些东西 来帮助以后会用到的人(°ー°") 那 ...
- android学习笔记(入门篇)
+号只是当你第一次定义一个资源ID的时候需要, 告诉SDK此资源ID需要被创建出来 对于所有的View默认的权重是0,如果你只设置了一个View的权重大于0,那么这个View将占据除去别的View本身 ...
最新文章
- 怎么在css中加横线分层,CSS分层
- Linux Kernel 3.10内核源码分析--块设备层request plug/unplug机制
- 一天学完spark的Scala基础语法教程九、迭代器(idea版本)
- Unity 8 和 Snap 将会是 Ubuntu 的未来
- Jq将字符串复制粘贴到剪贴板
- Spark源码分析:多种部署方式之间的区别与联系
- 生成jni的android.mk,Android Studio 3.5版本JNI生成SO文件详解
- 打破网络沉闷---QQ强制聊天工具再度现身!
- 【CS论坛】维护网络安全的四块基石
- 第七章_生成对抗网络(GAN)
- Android签名验证与反调试机制的对抗技术
- 教你写Makefile
- 删除flash助手推荐广告
- Python3.x 标准模块库目录(下篇)
- 3-D Quasi-Recurrent Neural Network for Hyperspectral Image Denoising
- 【系统集成项目管理】之项目质量管理
- 最快的计算机操作,世界十大最快的超级计算机
- 异构计算, GPU和框架选型指南
- Python基础与拾遗2:Python中的字符串与字符串格式化
- 初学Java时使用记事本开发出现的中文乱码问题