【Docker】学习笔记02:镜像、容器数据卷

4 篇文章 0 订阅
3 篇文章 0 订阅

Docker镜像

Docker 镜像是什么?

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码运行时的库环境变量配置文件所有应用直接打包,可以直接跑起来

如何获得镜像:

  • 从远程仓库下载
  • 朋友拷贝给你
  • 自己制作一个镜像DockerFile

Docker镜像加载原理

UnionFS(联合文件系统)

UnionFs (联合文件系统)

UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

Docker镜像加载原理

boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system),在 bootfs之上。包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。
在这里插入图片描述
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.

虚拟机是分钟级别,容器是秒级!

分层理解

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层层的在下载
在这里插入图片描述

思考:为什么Docker镜像要采用这种分层的结构呢?

最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过docker image inspect 命令

[root@izuf6hlvm1mj8gdbdctw0rz ~]# docker inspect redis
[
    {
        "Id": "sha256:621ceef7494adfcbe0e523593639f6625795cc0dc91a750629367a8c7b3ccebb",
        "RepoTags": [
            "redis:latest"
        ],
        "RepoDigests": [
            "redis@sha256:0f97c1c9daf5b69b93390ccbe8d3e2971617ec4801fd0882c72bf7cad3a13494"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-01-13T09:45:41.527587343Z",
        "Container": "16535cfaf84a4049b6c02840219e8473787d5610e29409049df3a41bbf77a333",
        "ContainerConfig": {
            "Hostname": "16535cfaf84a",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.0.10",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.10.tar.gz",
                "REDIS_DOWNLOAD_SHA=79bbb894f9dceb33ca699ee3ca4a4e1228be7fb5547aeb2f99d921e86c1285bd"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"redis-server\"]"
            ],
            "Image": "sha256:222c0cecc006d8c73a04a58b5fa15ebae171a6e82a8ee8650ae616f6f1798ef4",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "19.03.12",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.0.10",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.10.tar.gz",
                "REDIS_DOWNLOAD_SHA=79bbb894f9dceb33ca699ee3ca4a4e1228be7fb5547aeb2f99d921e86c1285bd"
            ],
            "Cmd": [
                "redis-server"
            ],
            "Image": "sha256:222c0cecc006d8c73a04a58b5fa15ebae171a6e82a8ee8650ae616f6f1798ef4",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 104285909,
        "VirtualSize": 104285909,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/146713550a8e34dfe4a7d35d0ff328cec0a3191e5609ec1215094ab5934c7f02/diff:/var/lib/docker/overlay2/160d8915bc5fa3b0b3d5ec0af895798fd79208274043de4d8f17de71d9dc525b/diff:/var/lib/docker/overlay2/10558d2d50be59c966a77b2bc981336254be4561ac53d6d84b8006825ccc9ecd/diff:/var/lib/docker/overlay2/e0a1fabb7e859b0030f7d561776ea4b63f87e08ff07ad7a3784749c09234b4ff/diff:/var/lib/docker/overlay2/a1022c2288548dfd9cb8a8d2f2cf25bc091bfd42ebd3fbaac6e5a0c75399fb94/diff",
                "MergedDir": "/var/lib/docker/overlay2/c9ca6ab9540156e58826153f045fe4b997ef5efba1be2449057d142b052011b9/merged",
                "UpperDir": "/var/lib/docker/overlay2/c9ca6ab9540156e58826153f045fe4b997ef5efba1be2449057d142b052011b9/diff",
                "WorkDir": "/var/lib/docker/overlay2/c9ca6ab9540156e58826153f045fe4b997ef5efba1be2449057d142b052011b9/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864",
                "sha256:8e14cb7841faede6e42ab797f915c329c22f3b39026f8338c4c75de26e5d4e82",
                "sha256:1450b8f0019c829e638ab5c1f3c2674d117517669e41dd2d0409a668e0807e96",
                "sha256:f927192cc30cb53065dc266f78ff12dc06651d6eb84088e82be2d98ac47d42a0",
                "sha256:a24a292d018421783c491bc72f6601908cb844b17427bac92f0a22f5fd809665",
                "sha256:3480f9cdd491225670e9899786128ffe47054b0a5d54c48f6b10623d2f340632"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

理解:

所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。

举一个简单的例子,假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,
就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创健第三个镜像层该像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点.
在这里插入图片描述

特点

Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

3)commit 镜像

docker commit #提交容器成为一个新的镜像

用法:docker commit -m=”提交的描述信息” -a=”作者” 容器id 目标镜像名:[TAG]

容器数据卷

什么是容器数据卷?

容器之间可以有一个数据共享的技术,将Docker容器中产生的数据同步到本地。
这就是卷技术:目录的挂载,将我们容器内的目录,挂载到linux上面,实现双向数据同步
总结:容器的持久化操作。容器内也是可以数据共享的!

使用数据卷:

挂载的第一种方式:直接使用命令挂载 -v
docker run -it -v 主机目录:容器内目录 容器名 /bin/bash

docker run -it -v /home/ceshi:/home centos /bin/bash

将centos容器中/home目录下文件挂载到主机下/home/ceshi目录下
挂载成功检测(在主机下输入):docker inspect 容器id
在这里插入图片描述
分别在容器和主机对应目录下新建文件,发现可以同步;
将容器停止,修改主机上测试文件内容,再重新将容器启动,发现数据仍然同步。

具名和匿名挂载

docker volume ls #列出所有挂载
  • 匿名挂载:-v 容器内目录
  • 具名挂载:-v 卷名:容器内目录
  • 指定路径挂载:-v /宿主机目录:容器内目录
  • 通过docker inspect 容器id 查看具体挂载目录

“所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/自定义的卷名/_data下,如果指定了目录,docker volume ls 是查看不到的。”

拓展

通过 -v 容器内路径: ro rw 改变读写权限;默认rw可读可写

  • ro #readonly 只读
  • rw #readwrite 可读可写
$ docker run -d -P —name nginx05 -v juming:/etc/nginx:ro nginx
$ docker run -d -P —name nginx05 -v juming:/etc/nginx:rw nginx

一旦设定了ro,则容器的权限随之改变为只读,所以只能从宿主机操作。

ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!

DockerFlie挂载

挂载的第二种方式:编写dockerfile脚本设置挂载目录
DockerFile 就是用来构建docker镜像的构建文件,就是命令脚本!
通过脚本可以生成镜像,镜像是一层一层的,所以脚本是一个一个的命令,每个命令就是一层!
编写dockerfile,设置挂载目录

创建一个dockerfile文件,名字可以随便 建议Dockerfile
dockerfile1 文件中的内容: 指令(大写) + 参数

$ vim dockerfile1
FROM centos # 当前这个镜像是以centos为基础的
VOLUME [“volume01”,”volume02”] # 挂载卷的卷目录列表(多个目录)
CMD echo “——-end——-# 输出一下用于测试
CMD /bin/bash # 默认走bash控制台

这里的每个命令,就是镜像的一层!
构建出这个镜像

[root@atong ~]# docker build -f dockerfile1 -t atong/centos .

  • -f dockerfile1 # f代表file,指这个当前文件的地址(这里是当前目录下的dockerfile1)
  • -t atong/centos # t就代表target,指目标镜像名(注意镜像名前不能加斜杠‘/’)
  • . # 表示生成在当前目录下 -t后一定要加个 . 要不然不成功

运行一个容器:docker run -it atong/centos /bin/bash
测试:在 atong/centos 镜像运行的容器内的 volume01 挂载目录下新建一个文件container.txt ,然后不退出在宿主机上通过命令:#docker inspect 容器id 查看 mounts 中的具体匿名挂载目录,进入该目录下查看是否 container.txt 文件已经同步,若同步则成功。
在这里插入图片描述
在这里插入图片描述

数据卷容器

两个或多个mysql同步数据:双向拷贝
实现容器间的数据共享:—volumes-from
用到的命令:

docker run -it —name docker01 atong/centos:latest #注意要加上版本号不然默认最新
docker run -it —name docekr02 —volumes-from docker01 84719eb2a4a5
docker attach 84719eb2a4a5
docker run -it —name docker03 —volumes-from docker01 atong/centos:latest
ctrl+p+q

docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 —name mysql01 mysql:5.7
docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 —name mysql02 —volumes-from mysql01 mysql:5.7 #将mysql02挂载到mysql01上

结论:容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值