Docker学习笔记-入门篇

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 --help

Usage:  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 --help

Usage:  docker load [OPTIONS]

Load an image from a tar archive or STDIN

Options:
  -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!

学习方式说明:
理解概念(一开始可以不需要理解有多深入,可以模棱两可),然后一定要实践,最后实践+理论相结合一次搞定这个知识!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值