Docker 數據管理 node
爲何要進行數據管理呢?由於當咱們在使用container時,可能會在裏面建立一些數據或文件,可是當咱們停掉或刪除這個容器時,這些數據或文件也會一樣被刪除,這是咱們並不想看見的事情,因此咱們要進行數據管理,實現持久化存儲python
在容器中管理數據主要有兩種方式: mysql
一.若是使用的是-v參數的方法指定掛載的數據卷web
其實本質都是在運行docker run命令時,使用-v參數將主機的某個目錄做爲容器的數據卷。使用-v掛載數據卷時有兩種狀況:sql
1.第一種狀況好比:docker
docker run -it -v $(pwd)/hostDirectory:/containerDirectory ubuntu;14.04
這種狀況掛載的就是本機的某個目錄到了容器的某個目錄上數據庫
這種狀況下須要注意下面的幾點內容:ubuntu
2.第二種狀況就是好比下面的一個例子:bash
userdeMacBook-Pro:~ user$ docker run -d -P --name web -v /webapp training/webapp python app.py
其並無指定要鏈接本地的什麼目錄,因此docker就會自動建立一個匿名的volume,並將其掛載到容器中的/webapp目錄上,從其返回的掛載信息可見:app
"Mounts": [ { "Type": "volume", "Name": "2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105", "Source": "/var/lib/docker/volumes/2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105/_data", "Destination": "/webapp", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ],
可見其匿名生成了一個2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105/_data目錄,將其掛載到了容器的/webapp目錄上
除了docker自動幫咱們建立volume外,咱們還能夠本身建立並查看相應的信息:
userdeMBP:~ user$ docker volume create myVolume myVolume userdeMBP:~ user$ docker volume ls DRIVER VOLUME NAME local 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637 local 49bfc006ae2ebc343cdf59c0af674d7e16f70466f2e9a186ac34e61deb0cb027 local 71a809c56c488bc15078d7b715ddda461eef698643bec14fe53237e66c12eb62 local 933a418456d65bafb6f77989ea120a2da8dd62c7efccd2828d2e716e3111c530 local myVolume userdeMBP:~ user$ docker volume inspect myVolume [ { "CreatedAt": "2018-12-18T09:23:22Z", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/myVolume/_data", "Name": "myVolume", "Options": {}, "Scope": "local" } ]
而後就可以使用這個數據卷,將其掛載到相應的容器中:
docker run -it -v myVolume:/mydata ubuntu:14.04
須要注意的內容是:
若是volume是空的,容器目錄非空,那麼docker會將容器目錄裏面的內容拷貝到volume中
若是volume中已經有內容,無論容器中有沒有內容,都會將容器中的內容覆蓋
二.使用的是Dockerfile
1.
固然,除了使用-v參數外,還可以在Dockerfile中使用VOLUME掛載數據卷
#Dockerfile
VOLUME /mydata
這樣docker也會建立一個匿名的volume,而後將其掛載到相應容器的/mydata目錄上,這樣,若是/mydata中是有數據的,將會拷貝到匿名volume中
它的效果和docker run -it -v /mydata imageName是同樣的
由於Dockerfile的方法每一次運行時都會自動生成一個匿名的volume,若是你想要在不一樣的容器之間共享數據的話,仍是要使用上面本身建立一個myVolume,而後將其掛載的方法:
docker run -it -v myVolume:/mydata ubuntu:14.04
2.
⚠️須要注意的一點:
在Dockerfile的VOLUME指令後面是不能對該volume進行任何更改的,好比:
FROM debian:wheezy RUN useradd foo VOLUME /data RUN touch /data/x //生成新文件夾 RUN chown -R foo:foo /data //更改權限
上面執行的結果與你預期是不符的,咱們原本但願touch
命令在鏡像的文件系統上運行,可是實際上它是在一個臨時容器的Volume上運行,因此應該作的是:
FROM debian:wheezy RUN useradd foo RUN mkdir /data && touch /data/x RUN chown -R foo:foo /data VOLUME /data
3.當咱們的鏡像是經過Dockerfile生成的,若是在Dockerfile中使用的本地目錄下的代碼須要更改時,爲了避免用每次更改都要從新運行build去生成一個新的鏡像,方法就是將將代碼所在的相應目錄掛在到數據捲上,好比:
COPY . /mydata #把當前的目錄拷貝到 skeleton
WORKDIR /mydata
解決辦法就是運行鏡像時,寫成:
docker run -d -p 80:5000 -v $(pwd):/mydata ubuntu:14.04
使用-v $(pwd):/mydata,這樣$(pwd)中的數據就會與容器/mydata中的數據同步,這樣修改時,會自動刷新數據
下面是比較詳細的講解
1) 數據卷
數據卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,能夠提供不少有用的特性:
⚠️數據卷的使用,相似於 Linux 下對目錄或文件進行 mount,鏡像中的被指定爲掛載點的目錄中的文件會隱藏掉,能顯示看的是掛載的數據卷。
建立一個數據卷
在用 docker run命令的時候,使用 -v 標記來建立一個數據卷並掛載到容器裏。
在一次 run 中屢次使用能夠掛載多個數據卷。
userdeMacBook-Pro:~ user$ docker run -d -P --name web -v /webapp training/webapp python app.py Unable to find image 'training/webapp:latest' locally latest: Pulling from training/webapp e190868d63f8: Pull complete 909cd34c6fd7: Pull complete 0b9bfabab7c1: Pull complete a3ed95caeb02: Pull complete 10bbbc0fc0ff: Pull complete fca59b508e9f: Pull complete e7ae2541b15b: Pull complete 9dd97ef58ce9: Pull complete a4c1b0cb7af7: Pull complete Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d Status: Downloaded newer image for training/webapp:latest 1ad71e9d38081c38dcd355fd7a438cd9f94503e8bc28e99a48c0738b51e7efef
注意:也能夠在 Dockerfile 中使用 VOLUME來添加一個或者多個新的捲到由該鏡 像建立的任意容器。
刪除數據卷
數據卷是被設計用來持久化數據的,它的生命週期獨立於容器,Docker不會在容器 被刪除後自動刪除數據卷,而且也不存在垃圾回收這樣的機制來處理沒有任何容器引用的數據卷。
若是須要在刪除容器的同時移除數據卷。能夠在刪除容器的時候使用 docker rm -v 這個命令。
掛載一個主機目錄做爲數據卷
使用 -v 標記也能夠指定掛載一個本地主機的目錄到容器中去
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
上面的命令加載主機的 /src/webapp目錄到容器的 /opt/webapp目錄。
這個功能在進行測試的時候十分方便,好比用戶能夠放置一些程序到本地目錄/src/webapp中,來查看容器是否正常工做。
本地目錄的路徑必須是絕對路徑,若是目錄不存在 Docker 會自動爲你建立它。
⚠️Dockerfile 中不支持這種用法,這是由於 Dockerfile 是爲了移植和分享用 的。然而,不一樣操做系統的路徑格式不同,因此目前還不能支持。
Docker 掛載數據卷的默認權限是讀寫,用戶也能夠經過 :ro 指定爲只讀。
docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py
查看數據卷的具體信息
查看的是上面運行的docker run -d -P --name web -v /webapp training/webapp python app.py命令生成的volume
userdeMacBook-Pro:~ user$ docker inspect web [ { "Id": "1ad71e9d38081c38dcd355fd7a438cd9f94503e8bc28e99a48c0738b51e7efef", "Created": "2018-12-15T09:34:23.600548467Z", "Path": "python", "Args": [ "app.py" ], ... "Mounts": [ { "Type": "volume", "Name": "2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105", "Source": "/var/lib/docker/volumes/2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105/_data", "Destination": "/webapp", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], ...
在輸出的內容中找到其中和數據卷相關的部分,能夠看到全部的數據卷都是建立在主機的 /var/lib/docker/volumes/下面的
掛載一個本地主機文件做爲數據卷——不推薦
-v 標記也能夠從主機掛載單個文件到容器中:
docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
這樣就能夠記錄在容器輸入過的命令了
⚠️若是直接掛載一個文件,不少文件編輯工具,包括 vi 或者sed --in-place ,可能會形成文件 inode 的改變,從 Docker 1.1 .0起,這會致使報錯誤信息。
因此最簡單的辦法就直接掛載文件的父目錄。
2) 數據卷容器——實現持續更新數據在容器間共享
數據卷容器,其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。
首先,建立一個名爲 dbdata 的數據卷容器:
docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres
而後其餘的容器就可以使用--volumes-from來掛載dbdata容器中的數據卷/dbdata :
$docker run -d --volumes-from dbdata --name db1 training/postgres $docker run -d --volumes-from dbdata --name db2 training/postgres
一個容器可使用超過一個的 --volumes-from參數來指定從多個容器掛載不一樣的數據卷
也能夠掛載其餘已經掛載了數據卷容器的容器來實現級聯掛載數據卷:
docker run -d --name db3 --volumes-from db1 training/postgres
⚠️:使用--volumes-from參數所掛載數據卷的容器本身不須要保持在運行狀態
若是刪除了掛載的容器(包括 dbdata、db1 和 db2),數據卷並不會被自動刪除。
因此若是想要刪除一個數據卷,必須在刪除最後一個還掛載着它的容器時使用docker rm -v命令來指定同時要刪除的數據卷
3)利用數據卷容器來備份、恢復、遷移數據卷
備份
首先使用 --volumes-from標記來建立一個加載 dbdata 容器卷的容器,並從主機掛載當前目錄到容器的 /backup 目錄,如:
docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
容器啓動後,使用了 tar命令來將 /dbdata 卷備份爲容器中的/backup/backup.tar 文件,同時也就會在主機當前目錄下生成名爲 backup.tar的文件。
恢復
若是要恢復數據到一個容器,首先建立一個帶有空數據卷的容器 dbdata2:
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
而後建立另外一個容器busybox,掛載 dbdata2 容器卷中的數據卷,也指定將數據卷中的內容掛載到容器中的/backup下,這樣該容器的/backup下就有了backup.tar文件,而後使用untar解壓備份文件/backup/backup.tar到掛載的容器卷中:
docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
爲了查看/驗證恢復的數據,能夠再啓動一個容器busybox掛載一樣的容器卷,而後運行ls /dbdata來查看:
docker run --volumes-from dbdata2 busybox /bin/ls /dbdata
4)學習docker volume命令的使用
1> 首先查看該命令的使用方式
userdeMBP:~ user$ docker volume --help //查看該命令的使用方式 Usage: docker volume COMMAND Manage volumes //管理數據卷 Commands: create Create a volume ,建立一個數據卷 inspect Display detailed information on one or more volumes 展現一個或多個數據卷的詳細信息 ls List volumes 列舉出全部現有的數據卷 prune Remove all unused local volumes 移除全部如今並無在使用的數據卷 rm Remove one or more volumes 移除指定的一個或多個數據卷 Run 'docker volume COMMAND --help' for more information on a command.
2> 列舉查看本地現有的volume
userdeMBP:~ user$ docker volume ls //查看以前生成的數據卷,都是匿名數據卷 DRIVER VOLUME NAME local 2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105 local 4f059cc319550b606b40d1198866fcc8822267a9d6631c8f44a24619d4fe312e local 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637 local 49bfc006ae2ebc343cdf59c0af674d7e16f70466f2e9a186ac34e61deb0cb027 local 71a809c56c488bc15078d7b715ddda461eef698643bec14fe53237e66c12eb62 local 933a418456d65bafb6f77989ea120a2da8dd62c7efccd2828d2e716e3111c530 local a49c6e5e7497f3d1bfcb11159a5144030e03fd7cba21e3bd6ac9b12cc6e8ea76
3> 詳細查看其中某一個volume的信息:
userdeMBP:~ user$ docker volume inspect 2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105 //詳細查看其中某一個數據卷的信息 [ { "CreatedAt": "2018-12-15T09:34:23Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105/_data", "Name": "2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105", "Options": null, "Scope": "local" } ]
4> 將其中不在使用的本地數據卷給刪除
userdeMBP:~ user$ docker volume prune //將其中不在使用的本地數據卷給刪除 WARNING! This will remove all local volumes not used by at least one container. Are you sure you want to continue? [y/N] y Deleted Volumes: //這是被刪除掉的數據卷 a49c6e5e7497f3d1bfcb11159a5144030e03fd7cba21e3bd6ac9b12cc6e8ea76 2e8085436ec33315c8c034a87097df301e9ce1c04a9a9f5ce007344c6cef3105 4f059cc319550b606b40d1198866fcc8822267a9d6631c8f44a24619d4fe312e Total reclaimed space: 77.23kB userdeMBP:~ user$ docker volume ls //這些是還剩下的數據卷 DRIVER VOLUME NAME local 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637 local 49bfc006ae2ebc343cdf59c0af674d7e16f70466f2e9a186ac34e61deb0cb027 local 71a809c56c488bc15078d7b715ddda461eef698643bec14fe53237e66c12eb62 local 933a418456d65bafb6f77989ea120a2da8dd62c7efccd2828d2e716e3111c530
5>本身手動建立一個非匿名的volume
userdeMBP:~ user$ docker volume create myVolume 而後能夠建立一個非匿名的數據卷myVolume myVolume userdeMBP:~ user$ docker volume ls DRIVER VOLUME NAME local 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637 local 49bfc006ae2ebc343cdf59c0af674d7e16f70466f2e9a186ac34e61deb0cb027 local 71a809c56c488bc15078d7b715ddda461eef698643bec14fe53237e66c12eb62 local 933a418456d65bafb6f77989ea120a2da8dd62c7efccd2828d2e716e3111c530 local myVolume userdeMBP:~ user$ docker volume inspect myVolume [ { "CreatedAt": "2018-12-18T09:23:22Z", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/myVolume/_data", "Name": "myVolume", "Options": {}, "Scope": "local" } ]
6)刪除容器
userdeMBP:~ user$ docker volume inspect 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637 [ { "CreatedAt": "2018-12-15T07:28:50Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637/_data", "Name": "6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637", "Options": null, "Scope": "local" } ] userdeMBP:~ user$ docker volume rm 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637 Error response from daemon: remove 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637: volume is in use - [b4a512f0230fa598e7e40171e0597ea6db0740105449314a1a3767dcaa4a0edb] userdeMBP:~ user$ docker inspect b4a512f0230fa598e7e40171e0597ea6db0740105449314a1a3767dcaa4a0edb //該容器正在運行,因此其掛載的數據卷是不能被刪除的 [ { "Id": "b4a512f0230fa598e7e40171e0597ea6db0740105449314a1a3767dcaa4a0edb", "Created": "2018-12-15T07:28:26.800359991Z", "Path": "/entrypoint.sh", "Args": [ "/etc/docker/registry/config.yml" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 3006, "ExitCode": 0, "Error": "", ... userdeMBP:~ user$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2084e92eea8c ubuntu:14.04 "/bin/bash" 7 hours ago Up 7 hours boring_jackson b4a512f0230f registry "/entrypoint.sh /etc…" 3 days ago Up 8 hours 0.0.0.0:5000->5000/tcp registry userdeMBP:~ user$ docker volume rm myVolume //而後刪除一個沒有使用的數據卷就成功了 myVolume
5)如今咱們進行一個例子小實驗:
1> 首先建立一個mysql1容器,生成mysql數據卷掛載在該容器的/var/lib/mysql目錄上
userdeMBP:~ user$ docker run -d -v mysql:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql Unable to find image 'mysql:latest' locally latest: Pulling from library/mysql a5a6f2f73cd8: Already exists 936836019e67: Pull complete 283fa4c95fb4: Pull complete 1f212fb371f9: Pull complete e2ae0d063e89: Pull complete 5ed0ae805b65: Pull complete 0283dc49ef4e: Pull complete a7e1170b4fdb: Pull complete 88918a9e4742: Pull complete 241282fa67c2: Pull complete b0fecf619210: Pull complete bebf9f901dcc: Pull complete Digest: sha256:b7f7479f0a2e7a3f4ce008329572f3497075dc000d8b89bac3134b0fb0288de8 Status: Downloaded newer image for mysql:latest 71f78959d2a823e55a723cde747ee833f52138bf04f0f8ec33189ea902bb2356
2>查看生成的mysql數據卷
userdeMBP:~ user$ docker volume ls //如今可見生成了一個mysql數據卷 DRIVER VOLUME NAME local 6dcce8fa7b5bed65b8bdf8cb91603cfa4e993439ec20e921a6742808b6478637 local 49bfc006ae2ebc343cdf59c0af674d7e16f70466f2e9a186ac34e61deb0cb027 local 71a809c56c488bc15078d7b715ddda461eef698643bec14fe53237e66c12eb62 local 933a418456d65bafb6f77989ea120a2da8dd62c7efccd2828d2e716e3111c530 local mysql userdeMBP:~ user$ docker volume inspect mysql //查看該數據卷的詳細內容 [ { "CreatedAt": "2018-12-18T10:21:16Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/mysql/_data", "Name": "mysql", "Options": null, "Scope": "local" } ]
3> 而後對朝該數據卷中寫入數據
userdeMBP:~ user$ docker exec -it mysql1 /bin/bash root@71f78959d2a8:/# mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.13 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.00 sec) mysql> create database docker; //生成一個新的數據庫 Query OK, 1 row affected (0.08 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | docker | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.01 sec) mysql> exit Bye root@71f78959d2a8:/# exit exit userdeMBP:~ user$ docker rm -f mysql1 //而後移除mysql1這個容器 mysql1
4> 而後從新打開一個mysql2容器,掛載以前生成的mysql數據卷,以驗證數據是否成功共享:
userdeMBP:~ user$ docker run -d -v mysql:/var/lib/mysql --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql 6f242e6fc8341f2b809f2d54bef294e718658a3db8c595dfc84955b5b4b0f7a8 userdeMBP:~ user$ docker exec -it mysql2 /bin/bash root@6f242e6fc834:/# mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.13 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; //而後查看數據庫,是能夠看見以前在容器mysql1上生成的docker數據庫的,可見數據成功共享了 +--------------------+ | Database | +--------------------+ | docker | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.01 sec) mysql>