一:前言
在Docker容器的實際使用中,經常會遇到容器的數據持久化,容器之間的數據共享等問題,通常我們有兩種解決方案:
1)數據卷(Data Volumes):就是將容器內數據直接映射到本地主機環境的指定文件目錄之中,可以理解為容器掛載一個虛擬數據卷然后
映射到一個主機目錄中
2)數據卷容器(Data Volume Containers):用專門的容器來掛載數據卷,其他容器通過掛載這個父容器來實現數據共享,這個專門掛載
數據卷的容器就是數據卷容器,簡單的總結就是有一個容器來專門管理數據的持久化和容器之間數據共享
前者常用於單一容器數據持久化,后者常用於多容器之間的數據共享和數據持久化
二:數據卷(Data Volumes)
我們可以在鏡像程序運行時通過"-v /主機目錄文件名:/容器目錄名" 命令,將容器卷指定一個主機目錄,這樣我們的程序運行的數據就可以持久
保存到這個映射的主機目錄文件當中。
我們舉一個實際的例子,此處用一個簡單.Asp Core程序為例子:
我們寫一個Asp Core web程序,然后請求這個程序的get()接口,這個接口會將記錄日志文件保存到服務器指定的文件中,從而通過這個程序實現
Docker容器數據的持久化(記錄日志到本地)
日志記錄類代碼
public class FileLogger
{
private static string sPath = AppContext.BaseDirectory + "filelogs";
public static void LogWrite(string Messge)
{
try
{
using (FileStream fs = new FileStream(FilePath(sPath), FileMode.Append))
{
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
{
sw.WriteLine(DateTime.Now.ToString("【HH:mm:ss】") + Messge);
sw.Close();
fs.Close();
}
}
}
catch (Exception)
{
}
}
public static void LogError(Exception ex)
{
LogWrite($"[數據日志記錄異常]\n|異常時間:{DateTime.Now.ToString()};\n|異常信息|{ex.Message};\n|異常位置|{ex.StackTrace.Trim()}");
}
private static string FilePath(string PathStr)
{
if (!Directory.Exists(PathStr))
{
Directory.CreateDirectory(PathStr);
}
return PathStr + "/" + GetFileName();
}
private static string GetFileName()
{
return DateTime.Now.ToString("yyyyMMdd") + ".txt";
}
}
接口調用代碼:
[HttpGet]
public dynamic Get()
{
FileLogger.LogWrite("這條日志會被保存到/root/webapi/logs/下面");
return "ok";
}
然后我們將這個程序打包,然后通過Dockerfile構建成成鏡像然后部署到Docker容器中
如果不會Linux打包部署Asp Core程序的建議先看這篇文章:傳送門
Dockerfile文件如下
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /data
COPY . .
EXPOSE 8083
ENV ASPNETCORE_URLS http://+:8083
ENTRYPOINT ["dotnet", "MyLog.dll"]
然后在包含Dockerfile的項目目錄下面運行命令構建鏡像(不要掉了最后面那個小數點):
$ docker build -t mylog .
鏡像構建完成后我們運行鏡像到容器中,此時我們就可以-v 命令指定數據卷
此處/root/webapi/logs代表主機目錄,/data/filelogs代表容器目錄
$ docker run --name=mylog -p 8083:8083 -d -v /root/webapi/logs:/data/filelogs mylog
容器運行成功后我們我們查看容器詳情
$ docker inspect 容器ID
我們可以看到"Mounts"節點下會有如圖顯示

最后我們測試一下,請求程序的get接口,然后在/root/webapi/logs可以看到我們記錄的日志文件

三 數據卷容器
如我我們經常需要多個容器之間進行數據共享我們需要用到命令“--volumes-from”
具體實例:
1)我們從倉庫拉一個centos的容器鏡像
$ docker pull centos
2)然后運行這個鏡像並創建一個數據卷掛載到/mydata
$ docker run -it -v /mydata --name mycentos centos
3)再運行兩個容器,在這兩個容器中使用--volumes-from來掛載mycentos容器中的數據卷.
$ docker run -it --volumes-from mycentos --name soncentos1 centos
$ docker run -it --volumes-from mycentos --name soncentos2 centos
此時,容器soncentos1和soncentos2都掛載同一個數據卷到相同的/mydata 目錄。三個容器任何一方在該目錄下的寫入數據,其他容器都可以看到。
注:
可以多次使用--volumes-from參數來從多個容器掛載多個數據卷。還可以從其他已經掛載了容器卷的容器來掛載數據卷。
使用--volumes-from參數所掛載數據卷的容器自身並不需要保持在運行狀態。
如果刪除了掛載的容器(包括dbdata、db1和db2),數據卷並不會被自動刪除。如果要刪除一個數據卷,必須在刪除最后一個還掛載着它
的容器時顯式使用docker rm -v命令來指定同時刪除關聯的容器。
