Docker容器数据管理(数据卷&数据卷容器)

一:前言

 在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命令来指定同时删除关联的容器。
posted @ 2019-11-13 18:25  骇客HK  阅读(1331)  评论(1编辑  收藏  举报