默認容器的數據是保存在容器的可讀寫層,當容器被刪除時其上的數據也會丟失,所以為了實現數據的持久性則需要選擇一種數據持久技術來保存數據。官方提供了三種存儲方式:Volumes、Bind mounts和tmpfs。前面還介紹了:Docker 服務終端 UI 管理工具
數據存儲方式
從現在開始,我們學習?Docker 容器的數據存儲方式,你也可以先了解一下Docker 數據持久化的三種方案。
Bind mount 會覆蓋容器中的文件,而 volume mount 則不會。即如果容器中已有文件,則會將文件同步到主機的目錄上。此方式與 Linux 系統的 mount 方式很相似,即是會覆蓋容器內已存在的目錄或文件,但并不會改變容器內原有的文件,當 umount 后容器內原有的文件就會還原。
數據卷(Volumes)
-
由docker創建和管理,且與主機的核心功能隔離
-
無論是命名還是匿名數據卷,都存儲在/var/lib/docker/volumes/下面
-
定義的數據卷可以在多個容器中同時使用,且不會自動刪除
-
允許容器將內容保存到遠端、云服務提供商、加密內容等等
掛在主機目錄(Bind mounts)
-
與數據卷相比,掛在主機目錄具有有限的功能
-
應用的文件或者目錄事先不需要存在,用時會自動創建
-
該方式允許訪問容器的敏感文件,可能會產生安全隱患
內存映射(tmpfs)
-
僅存儲在容器的內存中,永遠不會寫入文件系統
-
swarm服務使用tmpfs掛載將敏感信息掛載到容器中
數據卷 - volumes
數據卷是存儲在?Docker 容器的特定目錄下面
優勢說明
Docker Volumes 機制通常用來給 Docker 容器保存持久化數據,使用 Volumes 有很多優勢:
-
更容易進行備份和數據遷移
-
使用 Docker CLI 命令或者 Docker API 來管理
-
可以在 Linux 和 Windows 操作系統上使用
-
可以更安全得在多個容器中共享
-
Volume drivers 允許容器將內容保存到遠端、云服務提供商、加密 volume 內容
-
新 Volume 的內容可以被容器預先填充
Volumes 通常也優于容器的可寫層,使用 Volumes 不會增加容器的體積,并且 Volumes 的內容存儲在外部獨立于容器的生命周期。如果容器不產生持久化數據,可以考慮使用 tmpfs 內存映射(只保存在容器的內存中)的方式來避免數據存儲在其他可能的地方,避免增加容器的體積。
使用說明
最開始的時候 -v 或者 --volume 選項是給單獨容器使用,而 --mount 選項是給集群服務使用。但是從 Docker 17.06 開始,也可以在單獨容器上使用 --mount。通常來講 --mount 選項也更加具體和詳細。-v 選項將所有選項集中到一個值,而 --mount 選項將可選項分開。如果需要指定 volume driver 選項,那么必須使用 --mount 選項。
#?創建一個數據卷
$?docker?volume?create?my-vol#?查看所有的數據卷
$?docker?volume?ls#?查看指定數據卷的信息
$?docker?volume?inspect?my-vol
[{"Driver":?"local","Labels":?{},"Mountpoint":?"/var/lib/docker/volumes/my-vol/_data","Name":?"my-vol","Options":?{},"Scope":?"local"}
]#?移除指定數據卷的
$?docker?volume?rm?my-vol#?清除無主的數據卷
$?docker?volume?prune
#?啟動一個掛載數據卷的容器
$?docker?run?-d?-P?--name?web?\-v?my-vol:/wepapp?\training/webapp?python?app.py$?docker?run?-d?-P?--name?web?\--mount?source=my-vol,target=/webapp?\training/webapp?python?app.py#?啟動一個掛載數據卷的服務
$?docker?service?create?-d?--name?devtest-service?\--mount?source=myvol2,target=/app?\nginx:latest
#?掛載為只讀模式
$?docker?run?-d?--name=nginxtest?\-v?nginx-vol:/usr/share/nginx/html:ro?\nginx:latest#?type可以分為bind、volume、tmpfs,?默認為volume
#?source用于設置數據卷的名稱,匿名數據卷可以省略
#?target表示需要掛載到容器里面的地方
#?readonly表示掛載的內容為只讀模式,可選
#?volume-opt表示可以使用多次,可選
$?docker?run?-d?--name=nginxtest?\--mount?source=nginx-vol,destination=/usr/share/nginx/html,readonly?\nginx:latest
[3]?掛載遠程數據卷
#?插件sshfs允許您輕松地在容器中掛載遠程文件夾#?下載該插件
$?docker?plugin?install?--grant-all-permissions?vieux/sshfs#?使用該驅動創建ssh數據卷
$?docker?volume?create?--driver?vieux/sshfs?\-o?sshcmd=test@node2:/home/test?\-o?password=testpassword?\-o?port=3336?\sshvolume#?啟動該驅動程序創建卷創建容器
#?如果兩個容器配置了可信關系,就不需要設置volume-opt密碼了
$?docker?run?-d?\--name?sshfs-container?\--volume-driver?vieux/sshfs?\--mount?src=sshvolume,target=/app,?\volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword?\nginx:latest
掛載主機目錄 - bind mounts
掛載主機目錄是將主機中的特定目錄直接掛在到容器內部使用
使用說明
#?使用bind模式啟動容器
$?docker?run?-d?-it?--name?devtest?\-v?"$(pwd)"/target:/app?\nginx:latest$?docker?run?-d?-it?--name?devtest?\--mount?type=bind,source="$(pwd)"/target,target=/app?\nginx:latest#?看下對應的信息
$?docker?inspect?devtest
"Mounts":?[{"Type":?"bind","Source":?"/tmp/source/target","Destination":?"/app","Mode":?"","RW":?true,"Propagation":?"rprivate"}
],
#?掛載為只讀模式
$?docker?run?-d?-it?--name?devtest?\-v?"$(pwd)"/target:/app:ro?\nginx:latest$?docker?run?-d?-it?--name?devtest?\--mount?type=bind,source="$(pwd)"/target,target=/app,readonly?\nginx:latest
特殊屬性
$?docker?run?-d?-it?--name?devtest?\-v?"$(pwd)"/target:/app?\-v?"$(pwd)"/target:/app2:ro,rslave?\nginx:latest$?docker?run?-d?-it?--name?devtest?\--mount?type=bind,source="$(pwd)"/target,target=/app?\--mount?type=bind,source="$(pwd)"/target,target=/app2,readonly,bind-propagation=rslave?\nginx:latest
內存映射 - tmpfs
內存映射是將內存映射到容器內供容器內部使用
優勢說明
最開始 --tmpfs 是給單獨容器使用,而 --mount 選項是給 swarm 集群服務使用的。但是,從 Docker 17.06 開始,也可以在單獨容器上使用 --mount 了。通常說來,--mount 更明確,更冗長。最大的區別是 --tmpfs 標志不支持任何可配置選項。其中 --tmpfs 只能在容器中使用,而 swarm 集群則必須使用 --mount 來使用 tmpfs 內存映射。
使用說明
#?容器上使用
$?docker?run?-d?-it?--name?tmptest?\--tmpfs?/app?\nginx:latest$?docker?run?-d?-it?--name?tmptest?\--mount?type=tmpfs,destination=/app?\nginx:latest
日志驅動 - logs
在容器外部查看容器內部的日志輸出情況,便于排除和監控問題
可以利用 docker logs 命令,查看 Docker 容器內部應用程序運行時所產生的日志。可以免除首先進入 Docker 容器,再打開應用程序的日志文件的過程。docker logs 會監控容器中操作系統的標準輸出設備(STDOUT),一旦 STDOUT 有數據產生,就會將這些數據傳輸到另一個設備中,則被稱為日志驅動(Logging Driver)。
#?動態查看日志內容
$?docker?logs?-f?netdata
Docker 是怎樣做到的呢?我們使用 docker info 命令,可以看到 Docker 容器的相關信息,其中有一項 Logging Driver 的字段。
#?當前所設置的日志驅動類型
$?docker?info?|?grep?'Logging?Driver'
Logging?Driver:?json-file
我們可以在 docker run 命令中通過 --log-driver 參數來設置具體的 Docker 日志驅動,也可以通過 --log-opt 參數來指定對應日志驅動的相關選項。
docker?run?-d?-p?80:80?--name?nginx?\--log-driver?json-file?\?#?設置日志驅動--log-opt?max-size=10m?\?#?表示JSON文件最大為10MB,超過則生成新的文件--log-opt?max-file=3?\???#?表示JSON文件最多保存3個,超過則刪除多余文件nginx
#?當然,可以在配置文件中添加,全局生效
$?cat?/etc/docker/daemon.json
{"log-driver":?"syslog"
}#?修改配置之后重啟服務
$?sudo?systemctl?restart?docker
額外,需要注意的是,默認情況下,Docker 將日志存儲到一個日志文件。
#?檢查日志文件路徑
$?docker?inspect?--format='{{.LogPath}}'?netdata
/var/lib/docker/containers/556553bcb5xxx13cbc588a4-json.log#?查看實時日志信息
$?tail?-f?`docker?inspect?--format='{{.LogPath}}'?netdata`