Docker(3)-----对镜像进一步了解与容器数据卷

1. Docker镜像是什么

  1. 镜像是一种轻量级,可执行的独立软件包用来打包软件运行环境和基于运行环境开发的软件,它包含某个软件所需的所有内容,包括代码,运行时,库,环境变量和配置文件。
  2. 所有的应用,直接打包docker镜像,就可以直接跑起来。
  3. 如何得到镜像?从远程仓库获得,朋友copy,或者我们自己制作一个镜像。

2. Docker镜像加载原理

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

1. UnionFS(联合文件系统)

  1. UnionFS(联合文件系统): Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加(这一句是重点,一层层,分层结构),同时可以将不同目录挂载到同一个虚拟文件系统下。
  2. Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承, 基于基础镜像(没有父镜像), 可以制作各种具体的应用镜像。
  3. 特性: 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
  4. 好处:资源共享,节约空间。

2. 分层的理解

  1. 镜像都是一层层,类似叠蛋糕一样,一层层原料,最后组成一个蛋糕。
  2. 我们先拉取一个tomcat镜像,docker pull tomcat:jdk8-corretto,之后再拉取另一个tomcat镜像,docker pull tomcat:jdk11-corretto。
    在这里插入图片描述

3. 如何提交一个自己的镜像

1. 相关命令:commit

```powershell
1. docker commit 提交容器成为一个新的副本

2. docker commit -m=“提交的描述信息" -a=”作者“  容器id 目标镜像名:[tag]
```

2. 实战

  1. 我们都可以拉取的tomcat镜像中,webapps是空的,原来的欢迎页面等等都是在webapps.dist中,每次都要操作一下,就是觉得麻烦。
  2. 实现:自己提交一个镜像,使得每次运行这个tomcat镜像,直接有欢迎页面。
# 1. 先将tomcat运行起来
root@ubuntu:/home/mylinux# docker run -p 8080:8080 -d --name MyTomcat tomcat:jdk8-corretto
b56aec91e00fa6e0e7cc370502ad5479c6d7e9cb20c0e19d4dcee1239c8e78da

# 2. 进入tomcat容器
root@ubuntu:/home/mylinux# docker exec -it MyTomcat bash
bash-4.2# ls
BUILDING.txt  CONTRIBUTING.md  LICENSE  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  native-jni-lib  temp  webapps  webapps.dist  work

# 3. 将webapps.dist 内容复制到webapps中
bash-4.2# cd webapps.dist/
bash-4.2# ls
ROOT  docs  examples  host-manager  manager
bash-4.2# cp -r ./ ../webapps
bash-4.2# cd ../webapps
bash-4.2# ls
ROOT  docs  examples  host-manager  manager
bash-4.2# exit
exit

# 4. 提交commit自己的镜像
root@ubuntu:/home/mylinux# docker ps
CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS              PORTS                    NAMES
b56aec91e00f        tomcat:jdk8-corretto   "catalina.sh run"   5 minutes ago       Up 5 minutes        0.0.0.0:8080->8080/tcp   MyTomcat
# docker commit -m=“提交的描述信息" -a=”作者“  容器id 目标镜像名:[tag] 
root@ubuntu:/home/mylinux# docker commit -m "add webapps" b56aec91e00f MyTomcat:1.0
# 提示:名字必须是小写
invalid reference format: repository name must be lowercase
root@ubuntu:/home/mylinux#  
root@ubuntu:/home/mylinux# docker commit -m "add webapps" b56aec91e00f mytomcat:1.0
sha256:c20fc856cf0638357437ee7e02da8f4e77576de1faf705124060c0ed4546ab78

# 5. 查看结果
root@ubuntu:/home/mylinux# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED              SIZE
mytomcat                            1.0                 c20fc856cf06        About a minute ago   381MB
tomcat                              jdk8-corretto       cf20ebdc4989        30 hours ago         376MB

# 6. 测试,使用mytomcat镜像创建容器,直接运行,发现可以直接在浏览器输入ip:8081 看到欢迎页面
# 使用8081是因为之前容器已经使用了本地的8080端口了
root@ubuntu:/home/mylinux# docker run -p 8081:8080 -d --name mytomcat mytomcat:1.0
d9577281c3b0f86348dc27019b700b63d16ae64c8e65e1b40159257ae347f0ce

在这里插入图片描述

3. 小结

  1. 如果你想要保存当前容器的状态,就可以通过commit提交,获得一个镜像
  2. 就好比我们以前学习vm的时候,快照
  3. 命令:docker commit -m “提交信息” -a “作者” 容器id 目标镜像名:[tag]
  4. 注意是容器的id哦

4. 容器数据卷

1. 概念

  1. 我们知道容器相当于一台小型的虚拟机,有自己的文件系统,那如果数据都在容器中,而我们又删除容器,此时数据就会丢失,比如mysql的数据丢失则是一件很恐怖的事情。因此我们急需===>数据可以持久化.
  2. 容器之间可以有一个数据共享的技术,docker容器中产生的数据,同步到本地,这就是数据卷。
  3. 数据卷使用的是:目录的挂载,将我们容器内的目录,挂载到linux上面。
  4. 比如:mysql /usr/mysql =====> /home/mysql 挂载到了本地上。
  5. 容器的持久化和同步操作,容器间也是可以数据共享的
  6. 使用数据卷:
    直接使用命令来挂载 -v
    docker run -it -v 主机目录:容器内目录

2. 实战

1. 初步使用数据卷

# 1. 我们先准备个centos
root@ubuntu:/home/mylinux# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
7a0437f04f83: Pull complete 
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest

# 2. 在本地上创建一个文件夹,为了与centos挂载
root@ubuntu:/home/mylinux# cd ..
root@ubuntu:/home# mkdir centos
root@ubuntu:/home# ls
centos

# 3. 启动centos镜像。
# 使用命令来挂载 -v
# docker run -it -v 主机目录:容器内目录 运行的镜像
# 对于centos运行为什么要用-it 之前解释过了,在下面的博客中的其他命令,第一大点中有
# https://blog.csdn.net/xueyijin/article/details/111479219
# -v /home/centos:/home 意思是将本机的/home/centos文件与容器centos的/home直接绑定
root@ubuntu:/home# docker run -it -v /home/centos:/home centos 
[root@b0605f23b4f0 /]# 

# 4. 我们在centos容器内进入home目录下,创建一个test.txt文本
[root@b0605f23b4f0 /]# cd home/
[root@b0605f23b4f0 home]# touch test.txt
[root@b0605f23b4f0 home]# 
# 注意:看前面的标识,root@b0605f23b4f0 home 是centos容器的
# root@ubuntu 是本机ubuntu的
# 我们在本机上查看 home目录,惊奇发现有了。
root@ubuntu:/home/centos# ls
test.txt

# 5. 我们停止容器后,观察本机是否还有此文件
root@ubuntu:/home/centos# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
b0605f23b4f0        centos              "/bin/bash"         11 minutes ago      Up 11 minutes                           naughty_hoover
root@ubuntu:/home/centos# docker stop b0605f23b4f0
b0605f23b4f0
# 结果还在
root@ubuntu:/home/centos# ls
test.txt

# 6. 我们先不启动容器,直接在test.txt的文件夹中添加内容。
root@ubuntu:/home/centos# vi test.txt 
root@ubuntu:/home/centos# cat test.txt 
hello world

# 重新启动centos容器
root@ubuntu:/home# docker run -it -v /home/centos:/home centos
[root@51b8a28a3af3 /]# cd /home
# 惊奇发现,数据居然同步过去了。
[root@51b8a28a3af3 home]# cat test.txt 
hello world

# 7. 在centos容器中修改test.txt文件且删除centos容器以及镜像
[root@51b8a28a3af3 home]# echo I am centos > test.txt 
[root@51b8a28a3af3 home]# cat test.txt 
I am centos
[root@51b8a28a3af3 home]# exit
exit
root@ubuntu:/home# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
centos                              latest              300e315adb2f        2 weeks ago         209MB
# 直接删除镜像 跟容器
root@ubuntu:/home# docker rmi -f centos
Untagged: centos:latest
Untagged: centos@sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Deleted: sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55

# 查看本机的home目录下,发现还在
# 这就是数据卷 持久化的作用了
root@ubuntu:/home# cd centos/
root@ubuntu:/home/centos# ls
test.txt
root@ubuntu:/home/centos# cat test.txt 
I am centos

2. 实战mysql数据同步

# 1. 先拉取镜像
root@ubuntu:/home# docker pull mysql

# 在homt目录下创建两个文件
root@ubuntu:/home# mkdir mysql
root@ubuntu:/home# cd mysql/
root@ubuntu:/home/mysql# mkdir data
root@ubuntu:/home/mysql# ls
data
root@ubuntu:/home/mysql# cd ..
root@ubuntu:/home# 

# 2. 对于mysql的启动,前提说明
# MYSQL_ROOT_PASSWORD=自己的密码
# 本变量必填,它指定了 MySQL root 的用户的密码。
# /var/lib/mysql 是mysql的数据存放位置
# /home/mysql/data 是自己本机的映射
# 使用3308 是因为本机之前就安装了mysql
root@ubuntu:/home# docker run -it -d -p 3308:3306 -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql

# 3. 启动并加入容器
root@ubuntu:/home# docker run -it -d -p 3308:3306 -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql 
2f51cd5c2727ed7a72bfb5ea46b4771d25f1ed24586c609383ca71ef8c67d2b2
root@ubuntu:/home# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
2f51cd5c2727        mysql               "docker-entrypoint.s…"   6 seconds ago       Up 4 seconds        33060/tcp, 0.0.0.0:3308->3306/tcp   zealous_austin
root@ubuntu:/home# docker exec -it 2f51cd5c2727 bash
root@2f51cd5c2727:/# cd bin/
# 进入mysql服务        
root@2f51cd5c2727:/bin# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.22 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

# 4. 查看本机的homte/mysql/data文件中,发现有数据了,mysql持久化也做好了。
root@ubuntu:/home/mysql/data# ls
2f51cd5c2727.err  binlog.000002  ca.pem           #ib_16384_0.dblwr  ibdata1      ibtmp1        mysql.ibd           public_key.pem   sys
auto.cnf          binlog.index   client-cert.pem  #ib_16384_1.dblwr  ib_logfile0  #innodb_temp  performance_schema  server-cert.pem  undo_001
binlog.000001     ca-key.pem     client-key.pem   ib_buffer_pool     ib_logfile1  mysql         private_key.pem     server-key.pem   undo_002

# 5. 测试一下,创建一个helloworld数据库
# 在mysql容器中创建
mysql> create database helloworld
    -> ;
Query OK, 1 row affected (0.03 sec)

# 在本机home/mysql/data查看,发现有helloworld数据
root@ubuntu:/home/mysql/data# ls | grep helloworld 
helloworld

# 6. 停止原来的mysql容器,再创建一个新的mysql02容器,直接挂载/home/mysql/data数据
# 查看新的mysql02容器中,是否有helloworld数据库
# 停止原来的且删除原来容器
root@ubuntu:/home# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
2f51cd5c2727        mysql               "docker-entrypoint.s…"   11 minutes ago      Up 11 minutes       33060/tcp, 0.0.0.0:3308->3306/tcp   zealous_austin
root@ubuntu:/home# docker rm -f 2f51cd5c2727
2f51cd5c2727

# 创建新容器mysql02 并挂载之前的/home/mysql/data
root@ubuntu:/home# docker run -it -d -p 3308:3306 --name mysql02 -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql 
01bc338ad0ac6a3fdc751e049f1717b4d2fe4e350f9ffd307fb353d5dc9ed5ca
# 进入mysql容器
root@ubuntu:/home# docker exec -it mysql02 bash
root@01bc338ad0ac:/# cd bin/
# 查看mysql中是否有helloworld数据库
root@01bc338ad0ac:/bin# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.22 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| helleworld          |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

mysql> 

3. 初步小结

  1. 对于数据卷来说,尤其是根据上面mysql实战可以得出:
  2. 一开始本地 /home/mysql/data 中没有内容,会直接把mysql容器中的数据同步出来
  3. 我们之后删除了第一个mysql容器,并重新创建一个全新的mysql02容器,并挂载本地 /home/mysql/data,此时本地 /home/mysql/data是有数据的。
  4. 挂载后我们发现,本地 /home/mysql/data的数据同步到了新的mysql02容器中,因为有helloworld数据库了。
  5. 因此:大家有feel了吧。

5. 具名和匿名挂载(了解)

  1. 挂载也可以分为三种:

    1. 指定路径挂载--------> -v /宿主机路径:容器内路径
    2. 具名挂载----------->-v 卷名:容器内路径
    3. 匿名挂载----------->-v 容器内路径 
    
    # 没有多大区别,我们常用的是指定路径挂载
    # 用刚刚mysql来举例子 
    
    # 匿名(没有指定挂载路径)
    docker run -it -d -P -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
    
    # 具名(没有指定挂载路径,但是取了一个名字)
    docker run -it -d -P -v juming-mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
    
    # 指定
    docker run -it -d -P -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
    
    # 这里就提出一个问题 如果是匿名或者具名,那么挂载之后的东西放在哪里呢?
    # 使用docker volume ls 查看挂载
    root@ubuntu:/home/mysql/data# docker volume ls
    DRIVER              VOLUME NAME
    local               1c59e5f79225ce95c23d5a892d8de30759377cac03e333e564f71bea17b9f005
    local               2ebaaae9a2cb8a606318f0e5c822eff9602248bd6533b41cec7dcdc8e94ea3b1
    # 刚刚指定的具名挂载在这里,这也是为什么要具名了,方便查看
    # 如果是匿名的话,则就是后面一大串数据,实际上是容器的id
    local               juming-mysql
    
    # 查看这些卷的位置
    # docker volume inspect 卷名
    root@ubuntu:/home/mylinux# docker volume inspect juming-mysql 
    [
        {
            "CreatedAt": "2020-11-30T18:29:20-08:00",
            "Driver": "local",
            "Labels": null,
            # 数据卷的位置
            "Mountpoint": "/var/lib/docker/volumes/juming-mysql/_data",
            "Name": "juming-mysql",
            "Options": null,
            "Scope": "local"
        }
    ]
    
    # 进入查看
    root@ubuntu:/home/mysql/data# cd /var/lib/docker/volumes/juming-mysql/_data
    root@ubuntu:/var/lib/docker/volumes/juming-mysql/_data# ls
    44200fb24004.err  binlog.000002  ca.pem           #ib_16384_0.dblwr  ibdata1      #innodb_temp  performance_schema  server-cert.pem  undo_001
    auto.cnf          binlog.index   client-cert.pem  #ib_16384_1.dblwr  ib_logfile0  mysql         private_key.pem     server-key.pem   undo_002
    binlog.000001     ca-key.pem     client-key.pem   ib_buffer_pool     ib_logfile1  mysql.ibd     public_key.pem      sys
    
    # 小结
    所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx
    

6. 容器之间数据卷

  1. 容器之间(两个或者多个)也可以使用数据卷,进行数据的同步。
    在这里插入图片描述

  2. 使用的命令是 --volumes-from。

  3. 实践:

    # 1. 先拉取centos
    root@ubuntu:/home# docker pull centos
    
    # 2. 在本机的home目录下创建 container文件
    root@ubuntu:/home# mkdir container
    root@ubuntu:/home# ls
    container
    
    # 3. 启动一个centos1容器,并将home目录 挂载到本机/home/container
    # 注意:容器之间的数据卷,前提是要有挂载
    root@ubuntu:/home# docker run -it -d --name centos1 -v /home/container/:/home centos
    aef2ed44dafebbf19c1e48c587fe4a89558fadd3898176c64b6faf2c0674cced
    
    # 4. 启动centos2容器,并与centos1容器进行挂载
    root@ubuntu:/home# docker run -it -d --name centos2 --volumes-from centos1 centos    
    03b8fc40d736ac5f1fee151fe5e2cb7e4736cdbc156be62027fa96feae11feb5
    
    # 5. 之后进入centos1容器内/home目录下,创建test.txt
    root@ubuntu:/home# docker exec -it centos1 bash
    [root@aef2ed44dafe /]# cd home/
    [root@aef2ed44dafe home]# echo "" > test.txt
    
    # 6. 在本机上查看 /home/container目录,以及centos2容器/home目录
    # 在本机上
    root@ubuntu:/home/container# ls
    test.txt
    
    # centos2容器上
    [root@03b8fc40d736 home]# ls
    test.txt
    
    # 7. 之后在centos2容器上,疯狂修改
    [root@03b8fc40d736 home]# echo "" > hello.txt
    [root@03b8fc40d736 home]# echo "" > world.txt
    [root@03b8fc40d736 home]# ls
    hello.txt  test.txt  world.txt
    
    # 8. 在centos1容器上查看
    [root@aef2ed44dafe home]# ls
    hello.txt  test.txt  world.txt
    
    # 9. 把centos1停止并删除后,在centos2中疯狂修改,看看本地是否有同步
    # centos1停止并删除
    root@ubuntu:/home/container# docker rm -f centos1
    centos1
    
    # centos2中疯狂修改
    [root@03b8fc40d736 home]# echo "" > centos2.txt
    [root@03b8fc40d736 home]# echo "" > kkkk.txt   
    [root@03b8fc40d736 home]# ls 
    centos2.txt  hello.txt  kkkk.txt  test.txt  world.txt
    
    # 10. 查看本地是否同步
    # 同步
    root@ubuntu:/home/container# ls
    centos2.txt  hello.txt  kkkk.txt  test.txt  world.txt
    
  4. 小结:容器之间数据卷同步,前提是要有挂载数据卷容器的生命周期一直持续到没有容器使用为止。例如:上面的例子,如果我在启动一个centos3容器并–volume-from centos2,再把centos2停止并删除,再centos3容器上的修改,本地/home/container还是可以同步的。除非,都删除了。

其他相关文章学习

Docker(1)----初步认识

Docker(2)----命令的学习

Docker(3)----对镜像进一步了解与容器数据卷

Dokcer(4)----网络

Docker(5)----DockerFile的使用

Docker(6)----Docker-compose的使用

Docker(7)----CI/CD的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值