为什么要做数据持久化?
当容器运行期间产生的数据是不会在写镜像里面的,重新用此镜像启动新的容器就会初始化镜像,会加一个全新的读写层来保存数据。如果想做到数据持久化,Docker提供数据卷(Data volume)或者数据容器卷来解决问题,另外还可以通过commit提交一个新的镜像来保存产生的数据。
Docker数据持久化方案:
- 基于本机文件系统的Volume。可以执行
Docker create
或Docker run
时,通过-v
参数将主机的目录作为容器的数据卷。这部分功能便是基于本地文件系统的volume管理。 - 基于plugin的Volume,支持第三方的存储方案,比如NAS,AWS。
基于本机文件系统的Volume:
- Data Volume:挂载数据卷
- Bind Mouting: 挂载本地目录
数据持久化之Bind Mouting:
Bind Mounting 持久化的方式,则本地的目录文件和容器中的文件是同步的,如果本地的文件做了修改,那么容器中的文件也会修改。
1.创建本地目录新增数据并挂载到容器
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE webdata v1 b25ea02c5f1f 23 hours ago 127MB [root@localhost ~]# mkdir web [root@localhost ~]# touch web/test.txt [root@localhost ~]# docker run -itd --name webtest -v /root/web:/opt/ webdata:v1 1f5965ef6bea6604c7692012e3ac1419d869ad51b4e31ca16c915b17d4045e80
2.查看容器webtest中同步的数据
[root@localhost ~]# docker exec -it webtest ls /opt/ test.txt
3.修改容器/opt目录数据,查看本地是否同步修改
[root@localhost ~]# docker exec -it webtest touch /opt/1.txt [root@localhost ~]# docker exec -it webtest ls /opt/ 1.txt test.txt [root@localhost ~]# ls /root/web //查看本地目录数据是否同步 1.txt test.txt
持久化在生产中的应用---Nginx
1.在本机创建网页文件test.html
[root@localhost ~]# cat /usr/local/nginx/html/test.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Hello Docker! </h1> </body> </html> [root@localhost ~]# mv /usr/local/nginx/html/test.html /root/web [root@localhost ~]# ls /root/web test.html
2.书写Dockerfile来创建一个nginx测试镜像
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ed21b7a8aee9 6 weeks ago 127MB [root@localhost ~]# cd /root/web [root@localhost web]# cat >Dockerfile <<EOF //书写Dockerfile文件 > FROM nginx:latest > WORKDIR /usr/share/nginx/html > COPY test.html test.html //不写绝对路径默认拷贝当前目录文件 > EOF [root@localhost web]# ls Dockerfile test.html [root@localhost web]# docker build -t myweb:v1 . //构建myweb:v1容器 Sending build context to Docker daemon 3.072kB Step 1/3 : FROM nginx:latest ---> ed21b7a8aee9 Step 2/3 : WORKDIR /usr/share/nginx/html ---> Running in 0fc41b6e742e Removing intermediate container 0fc41b6e742e ---> 58162f0ab157 Step 3/3 : COPY test.html index.html ---> 2bda7f3e4192 Successfully built 2bda7f3e4192 Successfully tagged myweb:v1 [root@localhost web]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myweb v1 2bda7f3e4192 21 seconds ago 127MB
3.使用构建的myweb镜像启动一个容器
使用myweb:v1镜像启动容器mynginx,-v指定将本机/root/web目录挂载到容器/usr/share/nginx/html目录,-p指定将本机80端口映射到容器80端口。
[root@localhost web]# docker run -itd --name mynginx -v /root/web:/usr/share/nginx/html -p 80:80 myweb:v1 a9cfc24af49c08540614b7a79c24ba0723b0e3a1d2e05c7eaa21ef54b69ca76b
4.访问
5.本机修改挂载到容器的/root/web目录下test.html文件,查看容器内变化并访问
[root@localhost web]# sed -i "s/Hello Docker/Hello Nginx Page/g" test.html //修改本机挂载到容器的/root/web目录下的test.html文件内容 [root@localhost web]# docker exec -it mynginx cat /usr/share/nginx/html/test.html //查看容器中/usr/share/nginx/html/test.html文件的变化 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Hello Nginx Page! </h1> --》可以看到本机修改后已经同步容器也修改了 </body> </html>
6.进入容器内修改/usr/share/nginx/html/test.html文件,查看本机变化并访问
[root@localhost web]# docker exec -it mynginx /bin/bash root@a9cfc24af49c:/usr/share/nginx/html# sed -i "s/Hello Nginx Page/Docker Page/" test.html //修改容器内test.html文件内容,查看是否同步到本机目录 root@a9cfc24af49c:/usr/share/nginx/html# cat test.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Docker Page! </h1> </body> </html> [root@localhost web]# cat test.html //查看本机test.html文件是否已同步修改 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> <h1>Docker Page! </h1> --》可以看到已经同步修改 </body> </html>
7.查看本机test.html与容器内test.html文件的MD5值
[root@localhost web]# md5sum test.html //本机test.html文件 d87a8dfe0abc2eca57ae35421dabf951 test.html [root@localhost web]# docker exec -it mynginx md5sum /usr/share/nginx/html/test.html //容器内test.html文件 d87a8dfe0abc2eca57ae35421dabf951 /usr/share/nginx/html/test.html
最后:
使用Bind Mounting 持久化的方式,则本地的目录文件和容器中的文件是同步的,如果本地的文件做了修改,那么容器中的文件也会修改,即Bind mount会覆盖容器中的文件。