iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 7
0
DevOps

Docker獸 究極進化 ~~ Kubernetes獸系列 第 7

Day-7 解析 Docker Volume

前言

在預設的Docker daemon下,我們常會遇到幾種情況:

  1. 當該容器不再存在時,數據將不會持久保存,並且如果另一個Process需要它,則可能很難從容器中取出數據。
  2. 容器的可寫層與運行容器的主機緊密耦合。您不能輕易地將數據移動到其他地方。
  3. 寫入容器的可寫層需要 存儲驅動程序來管理文件系統。存儲驅動程序使用Linux內核提供聯合文件系統。與使用直接寫入主機文件系統的數據卷相比,這種額外的抽象降低了性能 。

為了解決這些問題就誕生了docker volume。

What is docker volume?

如前面章節描述,每個container都是獨立且封閉的,但有時候我們會想要不透過進入container就能改變內部的程式碼,或者是想要進行database升級並保留原本資料,這時就需要docker volume了。

下面是docker volume的structure,那我們接下來講解Docker實現Volume的原理

  • Volume: Container將Volume存放在Docker area,以Linux來說預設為Var/lib/docker/volume。
  • BindMount: 可以為主機路徑下任何地方。
  • tmpfsMount:主機的memory。

https://ithelp.ithome.com.tw/upload/images/20200922/20129737n1gaMqiM4u.png

Volume pros

  • 使container很簡單進行資料備份與遷移。
  • 可以簡單透過Docker CLI或是Docker API執行。
  • Volumes在Linux以及Windows上都可運作。
  • Volumes可以安全地使Containers間交流資料。
  • 可以透過Volumes儲存遠端或是Cloud上的資料
  • 可以使Container創建時初始建立所需資料。

How to use volumes?

-v or —mount

首先創建一個volume

$ docker volume create ironman-vol

啟動Container並掛載volume到指定路徑

docker run --name ironman -d -v ironman-vol:/usr/src/app/app -p 8100:8100 ghjjhg567/ironman:latest

若想查看volume

$ docker volume ls 
DRIVER              VOLUME NAME
local               cbd2c6d11ebe4f0f112798bf0b7989d56611ba6eb02a07e95517c0147dd0b354
local               ccaf125b25a2e1afe100d7147977ae5535e74e32c7c02246845ba6ae3a069c36
local               iron-volume

若想查看volume詳細資訊

$ docker volume inspect iron-volume
[
    {
        "CreatedAt": "2020-09-12T15:35:54Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/iron-volume/_data",
        "Name": "iron-volume",
        "Options": {},
        "Scope": "local"
    }
]

若想移除volume

$ docker volume rm iron-volume
iron-volume

Binding

以下為啟動Container並Binding指定路徑的做法

$ docker run --name ironman -d -v $(pwd)/app:/usr/src/app/app -p 8100:8100 ghjjhg567/ironman:latest
1536433a700ada79a5498e081daf26058b317ea6dd8c2f2be28eb54b8c7fd8ae

Tips: 如果是windows環境,請將$(pwd)改為%cd%

再將container外部的app資料夾與內部的app資料夾進行掛載後,我們來測試修改外部程式,內部會不會同步改變。

$ vim ./app/
import json

from flask import Blueprint
from flask_headers import headers

bp = Blueprint('sync', __name__)

@bp.route('/hc', methods=['GET'])
@headers({'Content-Type': 'text/json'})
@headers({'Cache-Control': 's-maxage=0, max-age=0'})
def hc():
    return_obj = {
        "message": 'This endpoint for web service health check with docker volume'
    }
    return json.dumps(return_obj, ensure_ascii=False)

我們將return_obj中的message進行修改,接下來我們進入container內部查看

$ docker exec -it ironman bash
$ cat ./app/api/v1/health.py
import json

from flask import Blueprint
from flask_headers import headers

bp = Blueprint('sync', __name__)

@bp.route('/hc', methods=['GET'])
@headers({'Content-Type': 'text/json'})
@headers({'Cache-Control': 's-maxage=0, max-age=0'})
def hc():
    return_obj = {
        "message": 'This endpoint for web service health check with docker volume'
    }
    return json.dumps(return_obj, ensure_ascii=False)

那到這邊也就證實volume是有運作的。那接下來就來講解volume & mount

How to bind mount?

$ docker run --name ironman -d --mount type=bind,source=$(pwd)/app,target=/usr/src/app/app -p 8100:8100 ghjjhg567/ironman:latest

Different with volume and mount

當使用-v在掛載路徑時,若該路徑不存在於本機,則會建立該路徑,如果將綁定到容器上的目錄不為空,那目錄現有的內容會被綁定的目錄給遮蓋

How to use tmpfs mount?

不同於volume and bind mound,tmpfs mount不需要實體路徑將資料儲存,他是暫時性地儲存在主機的記憶體當中,當Container停止時,就會移除資料,通常用來儲存暫存性資料以及敏感資料。

$ docker run --name ironman -d --mount type=tmpfs,destination=/usr/src/app/app -p 8100:8100 ghjjhg567/ironman:latest
$ docker run --name ironman -d --tmpfs /usr/src/app/app -p 8100:8100 ghjjhg567/ironman:latest

小結

在本章節我們練習了各種使用Docker storage的方式,讀者未來能夠因應不同需求而使用不同方式去儲存資訊。
https://ithelp.ithome.com.tw/upload/images/20200922/201297371BuLYNcyt7.png

Reference

https://docs.docker.com/storage/volumes/


上一篇
Day-6 乘載 Docker Image的靈魂 Docker Hub & Github Packages
下一篇
Day-8 解析 Docker Network
系列文
Docker獸 究極進化 ~~ Kubernetes獸30

尚未有邦友留言

立即登入留言