【Docker镜像原理&容器数据卷】

Docker镜像原理-commit镜像

一、镜像讲解

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

②、所有的应用,直接打包docker镜像,就可以直接跑起来!

(1)、如何得到镜像:

①、从远程的仓库下载
②、拷贝文件
③、自己做一个dockerfile

二、docker镜像加载原理

UnionFS(联合文件系统)

我们下载的时候看到的一层层就是这个!

UnionFS (联合文件系统):

Union文件系统( UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

(1)、特性︰
一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来
这样最终的文件系统会包含所有底层的文件和目录

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

(2)、bootis(boot file system):
bootis主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

(3)、rootfs (root file system):
在bootfs之上。包含的就是典型Linux系统中的/dev, /proc, /bin, letc等标准目录和文件rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。


三、docker镜像分层

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

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

在这里插入图片描述

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
在这里插入图片描述

(3)、特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!这一层就是我们通常说的容器层,容器之下的都叫镜像层!
在这里插入图片描述

四、commit镜像

(1)、docker commit提交容器成为一个新的副本

#命令和git的原理类似
docker commit -m=“提交描述的信息” -a=“作者” 容器ID 目标镜像名:TAG

实战测试:
#启动一个默认的tomcat
[root@localhost ~]# docker run -it -p 8080:8080 tomcat

#发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认 webapps下面是没有文件的!给它添加一份配置文件进去
root@c17e3c593edc:/usr/local/tomcat/webapps# ls
root@c17e3c593edc:/usr/local/tomcat/webapps# cd ..
root@c17e3c593edc:/usr/local/tomcat# cp -r  webapps.dist/* webapps
root@c17e3c593edc:/usr/local/tomcat# cd webapps
root@c17e3c593edc:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

#将我们修改了的镜像使用commit提交成为一个新的镜像,以后我们就可以使用这个新的镜像
[root@localhost ~]# docker commit -m="add webapps app" -a="grj" c17e3c593edc tomcat-1:1.0
sha256:a648200fa20fbd75dac8e44ec14271c73504e7608c51fad15dcfb55063c4a82b
[root@localhost ~]# 
[root@localhost ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
tomcat-1              1.0       a648200fa20f   5 seconds ago   684MB
nginx                 latest    605c77e624dd   3 months ago    141MB
tomcat                latest    fb5657adc892   4 months ago    680MB
redis                 latest    7614ae9453d1   4 months ago    113MB
hello-world           latest    feb5d9fea6a5   7 months ago    13.3kB
centos                latest    5d0da3dc9764   7 months ago    231MB
portainer/portainer   latest    580c0e4e98b0   13 months ago   79.1MB
elasticsearch         7.6.2     f29a1ee41030   2 years ago     791MB

docker commit -m=“add webapps app” -a=“grj” c17e3c593edc tomcat-1:1.0

dockerimages

总结:

这个commit打包镜像将当前的操作环境保存下来 ,这个有点类似于虚拟机的镜像。

容器数据卷

五、容器数据卷

(1)、概述:

将应用和环境打包成一个镜像,里面的数据文件存在容器当中,由docker挂载到容器,单不属于联合文件系统(Union File System),数据卷可以提供用于持续存储或共享数据的特性。

(2)、思考?

数据如果都在容器当中,如果我们删除容器,那么数据也会丢失!
如何将数据持久化?
容器之间的数据共享技术!docker容器里面产生的数据,同步到本地。
这就是卷技术,将容器内的数据挂载到Linux的文件目录上。

(3)、特点:

容器的持久化和同步操作,容器之间的数据也是可以共享的!

(4)、部署

  • 实战1
#使用命令的方式挂载卷
docker run -it -v 主机目录和容器内的目录进行映射

[root@localhost ~]# docker run -it -v /home/ceshi:/home centos /bin/bash
[root@localhost ~]# cd /home/
[root@localhost home]# ls
ceshi  nginx  test.java

#“使用docker inspect 容器ID” 命令查看元数据进行验证
#如果能看到下面的这些部分则意味着数据卷挂载成功
[root@localhost ceshi]# docker inspect d1ff4bfe15ba
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/ceshi",
                "Destination": "/home",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

#使用一下刚刚挂载好的数据卷
[root@d1ff4bfe15ba /]# cd /home
[root@d1ff4bfe15ba home]# ls
[root@d1ff4bfe15ba home]# touch test.txt
[root@d1ff4bfe15ba home]# ls
test.txt

[root@localhost ceshi]# pwd
/home/ceshi
[root@localhost ceshi]# ls
test.txt

#这里可以看到我们在Linux虚拟机上写入了一个文件,
可以即时同步到docker镜像上面
[root@localhost ceshi]# vi test.txt 
Hello,World!

[root@d1ff4bfe15ba home]# cat test.txt 
Hello,World!

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

docker inspect d1ff4bfe15ba

以后我们所有的操作都可以在宿主机上面挂载的目录下完成,操作会自动同步到docker容器内部。

  • 实战2:安装MySQL

思考:

安装MySQL后数据持久化的问题。

#下载MySQL镜像
[root@localhost ~]# docker pull mysql:5.7

#启动MySQL
-d:后台运行
-p:端口映射
-v:数据卷挂载
-e:环境的配置(例如修改密码)
--name:容器名字

[root@localhost ~]# docker run -d -p 3310: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
f0e606d5753cdff930a66ea67064330f64c66c163cdedaac826637d2c08a51fd

#使用SQLyug连接docker的mysql
#连接3310这个端口

#在本地创建一个数据库“test”,查看一下我们的映射路径
[root@localhost ~]# ls /home/mysql/data/
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql               private_key.pem  server-cert.pem  sys
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       performance_schema  public_key.pem   server-key.pem   test

#我们将容器删除,但是挂载到本地的数据卷仍未丢失,这个时候我们就已经实现了容器持久性的功能
[root@localhost ~]# docker rm -f mysql01
mysql01
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND        CREATED      STATUS             PORTS                                       NAMES
572b2fd27dc9   portainer/portainer   "/portainer"   4 days ago   Up About an hour   0.0.0.0:8088->9000/tcp, :::8088->9000/tcp   quizzical_hypatia
[root@localhost ~]# ls /home/mysql/data/
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql               private_key.pem  server-cert.pem  sys
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       performance_schema  public_key.pem   server-key.pem   test

docker pull mysql:5.7

docker run -d -p 3310: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 rm -f mysql01

docker ps

六、具名挂载和匿名挂载

#匿名挂载:不指定容器外的目录
-v 容器内的路径
docker -d -p --name nginx01 -v /etc/nginx nginx

#使用匿名挂载
[root@localhost ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx
1458102dc9e10460c8712590516c50e44657887ffc960f5e0388ec5d8718e835

#查看所有的volume的情况
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     2a7ea4aa7b409318572914e56af3c93ce85a9974d407f4ce6a039db7f350fdde
local     850e72abcdce033c05a222682f636f9591089908bed6e076545ccdfacdd7cb02

#使用具名挂载Nginx:通过-v 卷名:容器内路径
[root@localhost ~]# docker run -d -P --name nginx02 -v juming_nginx:/etc/nginx nginx
82ac6c740c7807d3a87c02cbad9958e170e39d2a7aa6e267e8585847009f0cfb
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     2a7ea4aa7b409318572914e56af3c93ce85a9974d407f4ce6a039db7f350fdde
local     850e72abcdce033c05a222682f636f9591089908bed6e076545ccdfacdd7cb02
local     juming_nginx

#查看卷的路径
[root@localhost ~]# docker volume inspect juming_nginx
[
    {
        "CreatedAt": "2022-04-24T17:18:54+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming_nginx/_data",
        "Name": "juming_nginx",
        "Options": null,
        "Scope": "local"
    }
]
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/*/_data
我们使用具名挂载都可以找到我们的一个卷,绝大多数的情况下我们使用的都是具名挂载

#如何确定是具名挂载还是匿名挂载,还是指定目录路径挂载
-v容器内路径  #匿名挂载
-v卷名:容器内路径  #具名挂载
-v/宿主机路径:容器内路径  #指定路径挂载!

#通过-v容器内路径:
rorw改变读写权限

#只读:roreadonly 
#可读可写:rwreadwrite 

#一旦这个了设置了容器权限,容器对我们挂载出来的内容就有限定了!

docker run -d -p --name nginx02 -v juming-nginx: /etc/nginx:ronginx
docker run -d -p --name nginx02 -v juming-nginx : /etc/nginx:rw nginx

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

docker run -d -P --name nginx01 -v /etc/nginx nginx

docker volume ls

docker volume inspect juming_nginx

docker run -d -p --name nginx02 -v juming-nginx: /etc/nginx:ronginx

docker run -d -p --name nginx02 -v juming-nginx : /etc/nginx:rw nginx

七、dockerfile

(1)、docker就是用来构建docker镜像的文件!
(2)、使用命令脚本生成一个镜像

#创建一个dockerfile文件
#写入文件的内容,脚本的一行命令对应的就是镜像的一层一层的操作
[root@localhost docker-test-volume]# cat docker-test1 
FROM centos

VOLUME ["volume01","volume02"]  //没有指定挂载目录【匿名挂载】

CMD echo "---end---"
CMD /bin/bash

#生成镜像
[root@localhost docker-test-volume]# docker build -f /home/docker-test-volume/docker-test1 -t grj/centos .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in b675053f69ad
Removing intermediate container b675053f69ad
 ---> 35dcc5c75613
Step 3/4 : CMD echo "---end---"
 ---> Running in e6556454ef08
Removing intermediate container e6556454ef08
 ---> fffe798b3763
Step 4/4 : CMD /bin/bash
 ---> Running in c6550f38e0ba
Removing intermediate container c6550f38e0ba
 ---> 0fe37490d4a0
Successfully built 0fe37490d4a0
Successfully tagged grj/centos:latest
[root@localhost docker-test-volume]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
grj/centos            latest    0fe37490d4a0   31 seconds ago   231MB
tomcat-1              1.0       a648200fa20f   38 hours ago     684MB
nginx                 latest    605c77e624dd   3 months ago     141MB
tomcat                latest    fb5657adc892   4 months ago     680MB
redis                 latest    7614ae9453d1   4 months ago     113MB
mysql                 5.7       c20987f18b13   4 months ago     448MB
hello-world           latest    feb5d9fea6a5   7 months ago     13.3kB
centos                latest    5d0da3dc9764   7 months ago     231MB
portainer/portainer   latest    580c0e4e98b0   13 months ago    79.1MB
elasticsearch         7.6.2     f29a1ee41030   2 years ago      791MB


#启动自己创建的一个容器
[root@localhost docker-test-volume]# docker run -it 0fe37490d4a0 /bin/bash
[root@f9551954f6cf /]# 

#查看挂载的数据卷目录
[root@f9551954f6cf /]# ls -l
total 0

... ...
drwxr-xr-x.   2 root root   6 Apr 25 02:45 volume01
drwxr-xr-x.   2 root root   6 Apr 25 02:45 volume02


#查看卷挂载的路径
[root@localhost ~]# docker inspect 1098aa9684dc
... ...

"Mounts": [
            {
                "Type": "volume",
                "Name": "f4bb2e1c512c1149f1bf0715191fdbb36d20148ec6c25fa12dc4fb42f767408e",
                "Source": "/var/lib/docker/volumes/f4bb2e1c512c1149f1bf0715191fdbb36d20148ec6c25fa12dc4fb42f767408e/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "a02f6d6a3874279247515847fbdd3fb753901b9d53e7d132c7787819c0c543f6",
                "Source": "/var/lib/docker/volumes/a02f6d6a3874279247515847fbdd3fb753901b9d53e7d132c7787819c0c543f6/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

#查看同步是否成功
[root@localhost ~]# cd /var/lib/docker/volumes/a02f6d6a3874279247515847fbdd3fb753901b9d53e7d132c7787819c0c543f6/_data
[root@localhost _data]# ls
container.txt

数据卷容器

一、多个容器同步数据

在这里插入图片描述

#启动容器多个容器并查找挂载目录
[root@localhost ~]# docker run -it --name centos01 grj/centos
[root@9f289f5ec06b /]# ls -lh
total 0
... ...
drwxr-xr-x.   2 root root   6 Apr 25 03:11 volume01
drwxr-xr-x.   2 root root   6 Apr 25 03:11 volume02

[root@localhost ~]# docker run -it --name centos02 --volumes-from centos01 grj/centos
[root@7532c7275fb0 /]# ls -l
total 0
... ...
drwxr-xr-x.   2 root root   6 Apr 25 03:11 volume01
drwxr-xr-x.   2 root root   6 Apr 25 03:11 volume02

#进入到容器01在挂载目录下新建一个文件
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS              PORTS                                       NAMES
7532c7275fb0   grj/centos            "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute                                               centos02
9f289f5ec06b   grj/centos            "/bin/sh -c /bin/bash"   11 minutes ago       Up 11 minutes                                                   centos01
572b2fd27dc9   portainer/portainer   "/portainer"             4 days ago           Up 43 minutes       0.0.0.0:8088->9000/tcp, :::8088->9000/tcp   quizzical_hypatia
[root@localhost ~]# docker attach 9f289f5ec06b
[root@9f289f5ec06b /]# cd volume01
[root@9f289f5ec06b volume01]# ls
[root@9f289f5ec06b volume01]# touch docker01
[root@9f289f5ec06b volume01]# ls
docker01

#在容器2上查看文件是否同步
[root@7532c7275fb0 /]# cd volume01
[root@7532c7275fb0 volume01]# ls
docker01

#启动第三个容器并将容器数据卷挂载到centos01
[root@localhost dockerfile]# docker run -it --name centos03 --volumes-from centos01 grj/centos

#在centos02挂载目录中新建文件
[root@b6dfd12a8e36 volume01]# touch test02.txt
[root@b6dfd12a8e36 volume01]# ls
test02.txt  test1.txt

#在centos容器上面查看
[root@364862191d15 volume01]# ls
test02.txt  test1.txt

在这里插入图片描述

二、多个MySQL实现数据共享

docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /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

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

三、DockerFile

(1)、用来构建docker镜像文件!

构建步骤:
1、编写一个docker文件、
2、docker build 构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(dockerhub、阿里云镜像仓库)

访问官方镜像仓库
在这里插入图片描述

在这里插入图片描述

很多官方的镜像往往是没有很多命令和其它的功能,通常需要我们自己去添加


四、DockerFile构建过程

(1)、基础知识
①、每个保留关键字(命令),都必须是大写字母
②、执行重上到下顺序执行
③、# 表示注释
④、每个指令都会创建提交一个新的镜像层,并提交!
在这里插入图片描述

docker镜像逐渐成为了项目实战交付的标准。

(2)、DockerFile:
构建文件,定义了一切的步骤,源代码
(3)、Dockerimages:
通过DockerFile构建生成的镜像,最终发布和运行的产品,最终发布和运行的产品
(4)、Docker容器:容器就是镜像运行起来提供服务

五、Dockerfile镜像命令

在这里插入图片描述

FROM        #基础镜像,一切从这里开始构建
MAINTAINER  #镜像是谁写的,,姓名+邮箱
RUN         #镜像构建的时候需要运行的命令
ADD         #步骤:tomcat镜像,这个tomcat压缩包,添加内容
WORKDIR     #镜像的目录
VOLUME      #挂载的目录
EXPOST      #暴露端口配置
CMD         #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT  #可以追加命令
ONBUILD     #当构建一个被继承,Dockerfile,这个时候就会运行ONBUILD 的指令,触发指令
COPY        #类似ADD,将我们的文件拷贝到镜像中
ENV         #设置环境变量
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值