能夠在執行docker create
或者docker run
的時候,經過-v
參數將主機的目錄做爲容器的數據卷。這部分功能即是基於本地文件系統的Volume管理。html
支持第三方的存儲方案,好比NAS、AWS等。mysql
以MySQL爲例,能夠查看官方的Dockerfile,當中用到了Volume。nginx
# 查看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
目錄下。git
再建立一個mysql2的容器:github
[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 ~]#
刪除這兩個容器:web
[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設置別名來方便咱們使用。sql
從新建立mysql1容器,在啓動的時候給volume設置別名docker
[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容器,建立一個數據庫shell
[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來預先指定容器中的數據存放路徑。數據庫
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的,沒法保持環境的一致性,影響開發效率。)