18、docker的持久化存储和数据共享

docker volume

1|018.1 Data Volume

1|1Docker持久化数据方案

  • 基于本地文件系统的Volume

  可以在执行docker create或者docker run的时候,通过-v参数将主机的目录作为容器的数据卷。这部分功能便是基于本地文件系统的Volume管理。

  • 基于plugin的Volume

  支持第三方的存储方案,比如NAS、AWS等。

1|2Data Volume 类型

  • 受管理的data volume,由docker后台自动创建
  • 绑定挂载的volume,具体挂载位置可以由用户指定

1|3通过例子来查看

  以MySQL为例,可以查看官方的Dockerfile,当中用到了Volume。

# 查看volume [root@docker ~]# docker volume ls [root@docker ~]# # 创建一个MySQL的容器 [root@docker ~]# docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql # 查看MySQL容器跑起来之后的volume [root@docker ~]# docker volume ls DRIVER VOLUME NAME local e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac [root@docker ~]# # 查看这个volume的想象信息 [root@docker ~]# docker volume inspect e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac [ { "CreatedAt": "2018-06-07T09:13:24Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac/_data", "Name": "e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac", "Options": null, "Scope": "local" } ] [root@docker ~]#

  可以看到,这个volume并不在容器当中,而是挂载到了宿主机的/var/lib/docker/volumes/e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac/_data目录下。

  再创建一个mysql2的容器:

[root@docker ~]# docker run -d --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql [root@docker ~]# docker volume ls DRIVER VOLUME NAME local a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225 local e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac [root@docker ~]# docker volume inspect a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225 [ { "CreatedAt": "2018-06-07T09:22:18Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225/_data", "Name": "a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225", "Options": null, "Scope": "local" } ] [root@docker ~]#

  删除这两个容器:

[root@docker ~]# docker stop mysql1 mysql2 [root@docker ~]# docker rm mysql1 mysql2 [root@docker ~]# docker volume ls DRIVER VOLUME NAME local a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225 local e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac [root@docker ~]#

  可以发现,volume在容器删除之后也不会被删除,可以防止容器删除之后数据也不存在了的问题。但是volume的名字非常不友好,不方便我们使用,但是我们可以在创建或者启动容器的时候给volume设置别名来方便我们使用。

1|4给volume起别名

  重新创建mysql1容器,在启动的时候给volume设置别名

[root@docker ~]# sudo docker run -d -v mysql:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql [root@docker ~]# docker volume ls DRIVER VOLUME NAME local mysql [root@docker ~]# docker volume inspect mysql [ { "CreatedAt": "2018-06-07T09:30:33Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/mysql/_data", "Name": "mysql", "Options": null, "Scope": "local" } ] [root@docker ~]#

  验证一下这个mysql的volume是否已经被使用:进入mysql1容器,创建一个数据库

[root@docker ~]# docker exec -it mysql1 /bin/bash root@5aa496b309cc:/# mysql -uroot Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.11 MySQL Community Server - GPL Copyright (c) 2000, 2018, 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 | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.01 sec) mysql> create database docker; Query OK, 1 row affected (0.07 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | docker | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> \q Bye root@5aa496b309cc:/# exit [root@docker ~]# 停止mysql1容器,并删除mysql1容器 [root@docker ~]# docker stop mysql1 [root@docker ~]# docker rm mysql1 [root@docker ~]# 创建一个新的mysql2的容器,急需使用mysql这个volume [root@docker ~]# sudo docker run -d -v mysql:/var/lib/mysql --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql [root@docker ~]# 进入mysql2查看是否存在之前的数据 [root@docker ~]# docker exec -it mysql2 /bin/bash root@cf1cc3ad331e:/# mysql -uroot Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.11 MySQL Community Server - GPL Copyright (c) 2000, 2018, 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 | +--------------------+ | docker | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> \q Bye root@cf1cc3ad331e:/# exit

  可以发现,volume中的数据并不会因为容器的删除二消失,实现了数据持久化的目标。但是这种方式的volume需要在Dockerfile中使用VOLUME来预先指定容器中的数据存放路径。

2|018.2 Bind Mounting

  Bind Mounting跟上面的方式不一样,可以动态的指定容器内文件存放路径和宿主机上的数据库卷目录。

  构建一个docker-nginx的镜像:

# Dockerfile [root@docker docker-nginx]# cat Dockerfile # this same shows how we can extend/change an existing official image from Docker Hub FROM nginx:latest # highly recommend you always pin versions for anything beyond dev/learn WORKDIR /usr/share/nginx/html # change working directory to root of nginx webhost # using WORKDIR is prefered to using 'RUN cd /some/path' COPY index.html index.html # I don't have to specify EXPOSE or CMD because they're in my FROM [root@docker docker-nginx]# cat index.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Hello Docker! </h1> </body> </html> [root@docker docker-nginx]# 构建镜像 [root@docker docker-nginx]# docker build -t staryjie/docker-nginx . [root@docker docker-nginx]# 创建容器 [root@docker docker-nginx]# docker run -d -p 80:80 --name web staryjie/docker-nginx [root@docker docker-nginx]# 本地访问 [root@docker docker-nginx]# curl 127.0.0.1 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Hello Docker! </h1> </body> </html> [root@docker docker-nginx]#

  但是index.html文件是无法更改的,如果要更改必须要重新构建镜像,这样非常不便。

[root@docker docker-nginx]# 强制删除web容器 [root@docker docker-nginx]# docker rm -f web [root@docker docker-nginx]# 重新创建一个容器,指定宿主机上index.html的目录到容器中nginx的html目录 [root@docker docker-nginx]# docker exec -it web1 /bin/bash root@18af473954f1:/usr/share/nginx/html# ls Dockerfile index.html root@18af473954f1:/usr/share/nginx/html# touch test.txt root@18af473954f1:/usr/share/nginx/html# exit [root@docker docker-nginx]# ls Dockerfile index.html test.txt [root@docker docker-nginx]# curl 127.0.0.1 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Hello Docker! </h1> </body> </html> [root@docker docker-nginx]# 修改index.html [root@docker docker-nginx]# cat index.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Hello Docker! </h1> <h1>Hello, I have changed this file! </h1> </body> </html> [root@docker docker-nginx]# curl 127.0.0.1 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Hello Docker! </h1> <h1>Hello, I have changed this file! </h1> </body> </html> [root@docker docker-nginx]#

  采用Bind Mounting的方式实现volume的话,容器内外的数据是同步的,只需要修改一个地方,容器内或者容器外都会同步修改,非常的方便快捷。

  采用Bind Mounting的方式,将docker作为开发环境可以使我们的开发环境和生产环境保持一致,这也是实现DevOps的第一步。(很多开发使用的都是Windows的系统,但是服务器一般都是Linux的,无法保持环境的一致性,影响开发效率。)

  利用docker搭建一个与生产环境统一的开发环境


__EOF__

本文作者StaryJie
本文链接https://www.cnblogs.com/jie-fang/p/10279773.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   StaryJie  阅读(3774)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示