Docker 與 K8S學習筆記(十 二)容器間資料共享

阿拉懶神燈發表於2022-01-15

資料共享是volume的關鍵特性,今天我們來看一下通過volume實現容器與host、容器與容器之間共享資料。

 

一、容器與host共享資料

在上一篇中介紹到的bind mount和docker manage volume,它們都可以實現容器與host之間共享資料,只是方式有所區別,bind mount在容器啟動前便指定了volume所在host資料目錄,並掛載到容器中了,容器啟動後,我們向此目錄寫入資料,容器也能使用這些資料,而對於docker manage volume,有所不同,它在容器啟動時才能確定volume所在host的目錄,所以這裡就需要用到docker cp 命令,它可以在容器和host之間複製資料。

$ sudo docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd
0320b31996408b61a1bc363f999509f3bfdc17ca292dd08bd5f7496edb7c8947
$ sudo docker cp ~/htdocs/index.html 0320b31996:/usr/local/apache2/htdocs
$ curl http://127.0.0.1:80
<h1>update page</h1>

 

二、容器之間共享資料

1、bind mount

第一種方式還是bind mount,將要共享的資料通過bind mount掛載到多個容器上,例如,我們啟動三個httpd容器,並讓它們掛載相同的htdocs。

$ sudo docker run --name web1 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
f5a911434445f431d511b5292112fe0f9b9b44b868f98561feba895107e0cb40
$ sudo docker run --name web2 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
61e43e584c33efdab7ef5c1a72a5a4e9a0d40731d860e5fd9fb23de0a7c767df
$ sudo docker run --name web3 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
6494f68481a0f1971fdc33c13b969706c69b8ecaedc39aa707b6d35d32b6fba0
$ sudo docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED          STATUS          PORTS                                     NAMES
6494f68481a0   httpd     "httpd-foreground"   11 seconds ago   Up 9 seconds    0.0.0.0:49155->80/tcp, :::49155->80/tcp   web3
61e43e584c33   httpd     "httpd-foreground"   19 seconds ago   Up 17 seconds   0.0.0.0:49154->80/tcp, :::49154->80/tcp   web2
f5a911434445   httpd     "httpd-foreground"   28 seconds ago   Up 27 seconds   0.0.0.0:49153->80/tcp, :::49153->80/tcp   web1
$ curl http://127.0.0.1:49155
<h1>hello docker</h1>
$ curl http://127.0.0.1:49154
<h1>hello docker</h1>
$ curl http://127.0.0.1:49153
<h1>hello docker</h1>

2、volume container

volume container是專門為其他容器提供volume的容器,它提供的volume可以是bind mount也可以是docker manage volume,我們首先建立一個volume container:

$ sudo docker create --name vc_data -v ~/htdocs:/usr/local/apache2/htdocs -v /other/useful/tools busybox
178dd66f492dbe0485816a9f6f9ecde97c03e322841e6b38f4a2c7c439c6f020

我們掛載了兩個volume,一個是使用bind mount掛載web靜態頁面,另一個使用docker manage volume掛載常用工具。注意我們使用docker create命令,這是因為volume container的作用只是提供資料,它本身不需要處於執行狀態。

通過docker inspect可以看到這兩個volume:

$ sudo docker inspect vc_data
[
   ...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/yangye/htdocs",
                "Destination": "/usr/local/apache2/htdocs",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",
                "Name": "e3ba7240ef18694660ed3da4e6976fa35bb5c2d3c26f91593ea30d26289e0fd6",
                "Source": "/var/lib/docker/volumes/e3ba7240ef18694660ed3da4e6976fa35bb5c2d3c26f91593ea30d26289e0fd6/_data",
                "Destination": "/other/useful/tools",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ...
 ]

接著我們在啟動容器時通過--volumes_from使用剛建立的vc_data:

$ sudo docker run --name web1 -d -p 80 --volumes-from vc_data httpd
14131cc7057528ac892b2661ed46e543bb30b65af789d83f0770dab4ebb06a33
$ sudo docker run --name web2 -d -p 80 --volumes-from vc_data httpd
320a11bcb64ee032c65b65ee744a7afd6ebc7a24330e68c688a4b9c4b5e5eb22
$ sudo docker run --name web3 -d -p 80 --volumes-from vc_data httpd
f4c4bed873f3ad76b37136fc93dd915c6e4915897e7628f3b1ca1d5fc30e920a

我們以web1為例看看它的volume是否正確:

$ sudo docker inspect web1
[
   ...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/yangye/htdocs",
                "Destination": "/usr/local/apache2/htdocs",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",
                "Name": "e3ba7240ef18694660ed3da4e6976fa35bb5c2d3c26f91593ea30d26289e0fd6",
                "Source": "/var/lib/docker/volumes/e3ba7240ef18694660ed3da4e6976fa35bb5c2d3c26f91593ea30d26289e0fd6/_data",
                "Destination": "/other/useful/tools",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ...

可見,web1使用的就是vc_data的volume,我再來驗證下資料共享的效果:

$ sudo docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED          STATUS          PORTS                                     NAMES
f4c4bed873f3   httpd     "httpd-foreground"   10 minutes ago   Up 10 minutes   0.0.0.0:49158->80/tcp, :::49158->80/tcp   web3
320a11bcb64e   httpd     "httpd-foreground"   10 minutes ago   Up 10 minutes   0.0.0.0:49157->80/tcp, :::49157->80/tcp   web2
14131cc70575   httpd     "httpd-foreground"   10 minutes ago   Up 10 minutes   0.0.0.0:49156->80/tcp, :::49156->80/tcp   web1
$ curl http://127.0.0.1:49158
<h1>hello docker</h1>
$ curl http://127.0.0.1:49157
<h1>hello docker</h1>
$ curl http://127.0.0.1:49156
<h1>hello docker</h1>

三個容器都共享了volume_container中的volume,相比於bind mount,我們發現volume container具備以下特點:

1)不必為每一個容器指定host path,所有path都在volume container中定義好了,容器只需和volume container關聯,實現了容器與host的解耦;

2)使用volume container的容器,其mount point都是一致的,有利於配置的規範和標準化,當然這樣也存在一定的侷限使用時需要綜合考慮。

相關文章