Docker之实现挂载的三种方式汇总

 更新时间:2023年02月25日 14:06:58   作者:一只菜狗  
这篇文章主要介绍了Docker之实现挂载的三种方式汇总,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Docker实现挂载的方式

在介绍VOLUME指令之前,我们来看下如下场景需求:

1.容器是基于镜像创建的,最后的容器文件系统包括镜像的只读层+可写层,容器中的进程操作的数据持久化都是保存在容器的可写层上。一旦容器删除后,这些数据就没了,除非我们人工备份下来(或者基于容器创建新的镜像)。能否可以让容器进程持久化的数据保存在主机上呢?这样即使容器删除了,数据还在。

2. 当我们在开发一个web应用时,开发环境是在主机本地,但运行测试环境是放在docker容器上。这样的话,我在主机上修改文件(如html,js等)后,需要再同步到容器中。这显然比较麻烦。

3. 多个容器运行一组相关联的服务,如果他们要共享一些数据怎么办?

对于这些问题,我们当然能想到各种解决方案。而docker本身提供了一种机制,可以将主机上的某个目录与容器的某个目录(称为挂载点、或者叫卷)关联起来,容器上的挂载点下的内容就是主机的这个目录下的内容,这类似linux系统下mount的机制。 这样的话,我们修改主机上该目录的内容时,不需要同步容器,对容器来说是立即生效的。 挂载点可以让多个容器共享。

下面我们来介绍具体的实现机制。

一、通过docker run命令

1.运行命令:docker run --name test -it -v /home/xqh/myimage:/data ubuntu /bin/bash

其中的 -v 标记 在容器中设置了一个挂载点 /data(就是容器中的一个目录),并将主机上的 /home/xqh/myimage 目录中的内容关联到 /data下。

这样在容器中对/data目录下的操作,还是在主机上对/home/xqh/myimage的操作,都是完全实时同步的,因为这两个目录实际都是指向主机目录。

2.运行命令:docker run --name test1 -it -v /data ubuntu /bin/bash

上面-v的标记只设置了容器的挂载点,并没有指定关联的主机目录。这时docker会自动绑定主机上的一个目录。通过docker inspect 命令可以查看到。

xqh@ubuntu:~/myimage$ docker inspect test1
[
{
    "Id": "1fd6c2c4bc545163d8c5c5b02d60052ea41900a781a82c20a8f02059cb82c30c",
.............................
    "Mounts": [
        {
            "Name": "0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01",
            "Source": "/var/lib/docker/volumes/0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01/_data",
            "Destination": "/data",
            "Driver": "local",
            "Mode": "",
            "RW": true
        }
    ],

上面 Mounts下的每条信息记录了容器上一个挂载点的信息,“Destination” 值是容器的挂载点,"Source"值是对应的主机目录。可以看出这种方式对应的主机目录是自动创建的,其目的不是让在主机上修改,而是让多个容器共享。

二、通过dockerfile创建挂载点

上面介绍的通过docker run命令的-v标识创建的挂载点只能对创建的容器有效。通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点。

还有一个区别是,通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。

#test
FROM ubuntu
MAINTAINER hello1
VOLUME ["/data1","/data2"]

上面的dockfile文件通过VOLUME指令指定了两个挂载点 /data1 和 /data2.

我们通过docker inspect 查看通过该dockerfile创建的镜像生成的容器,可以看到如下信息

"Mounts": [
    {
        "Name": "d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21",
        "Source": "/var/lib/docker/volumes/d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21/_data",
        "Destination": "/data1",
        "Driver": "local",
        "Mode": "",
        "RW": true
    },
    {
        "Name": "6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36",
        "Source": "/var/lib/docker/volumes/6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36/_data",
        "Destination": "/data2",
        "Driver": "local",
        "Mode": "",
        "RW": true
    }
],

可以看到两个挂载点的信息。

三、容器共享卷(挂载点)

下面我们创建另一个容器可以和test1(已经创建好的容器)共享 /data1 和 /data2卷,这是在 docker run中使用 --volumes-from标记,如:

可以是来源不同镜像,如:

docker run --name test2 -it --volumes-from test1 ubuntu /bin/bash

也可以是同一镜像,如:

docker run --name test3 -it --volumes-from test1 myimage /bin/bash

上面的三个容器 test1 , test2 , test3 均有 /data1 和 /data2 两个目录,且目录中内容是共享的,任何一个容器修改了内容,别的容器都能获取到。

四、最佳实践:数据容器

如果多个容器需要共享数据(如持久化数据库、配置文件或者数据文件等),可以考虑创建一个特定的数据容器,该容器有1个或多个卷。

其它容器通过–volumes-from 来共享这个数据容器的卷。

因为容器的卷本质上对应主机上的目录,所以这个数据容器也不需要启动。

如: docker run --name dbdata myimage echo “data container”

说明:有个卷,容器之间的数据共享比较方便,但也有很多问题需要解决,如权限控制、数据的备份、卷的删除等。以后在介绍。

关于Docker中挂载的解释

现在有这么一个命令:

docker run -p 33061:3306 --name mysql  --restart=always -e MYSQL_ROOT_PASSWORD=pisen  -v /etc/localtime:/etc/localtime:ro  -v /etc/timezone:/etc/timezone:ro  -d mysql:5.7

因为着重要说挂载的问题,就单独揪出来参数来说

-v /etc/localtime:/etc/localtime:ro

就是将  宿主机的/etc/localtime文件挂载到容器的/etc/localtime 文件,并且容器内的/etc/localtime文件设置为只读(:ro)

实际的效果就是mysql容器启动后,时间时区的设置,使用的就是宿主机的 /etc/localtime 文件内设置的内容起作用。

如果没有设置只读的情况下,该挂载实现的效果是:

情况1:使用echo命令去修改

echo 'lq' > timezone

无论更改宿主机上的/etc/localtime文件内容还是修改容器内的/etc/localtime文件内容,都会影响到对方。  

情况2:使用vi命令去修改

vi timezone

则无论修改哪边都不会影响到另外一方的文件内容。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Docker 安装 MySQL(8和5.7)

    Docker 安装 MySQL(8和5.7)

    这篇文章主要介绍了Docker 安装 MySQL(8和5.7),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • 使用Docker-compose离线部署Django应用的方法

    使用Docker-compose离线部署Django应用的方法

    这篇文章主要介绍了使用Docker-compose离线部署Django应用的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • docker容器连接宿主机redis与mysql的配置方法

    docker容器连接宿主机redis与mysql的配置方法

    最近有朋友在工作时遇到一个问题,docker容器无法访问宿主机的redis,所以这里给大家总结下,这篇文章主要给大家介绍了关于docker容器连接宿主机redis与mysql的配置方法,需要的朋友可以参考下
    2023-06-06
  • Docker部署UI自动化测试环境的实现步骤

    Docker部署UI自动化测试环境的实现步骤

    本文主要介绍了Docker部署UI自动化测试环境的实现步骤,通过Docker可以快速创建、部署和测试脚本,提高测试效率,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • Docker拉取镜像超时的原因分析与解决方法

    Docker拉取镜像超时的原因分析与解决方法

    这篇文章主要为大家详细介绍了Docker在拉取镜像时超时的相关原因分析与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-04-04
  • 如何打jar包为Docker镜像并部署

    如何打jar包为Docker镜像并部署

    这篇文章主要介绍了打jar包为Docker镜像并部署,通过将应用程序打包为Docker镜像,并在容器中运行,可以提供更高的灵活性、可移植性和可靠性,简化应用程序的部署和管理,提升开发和运维效率,降低系统运行成本,需要的朋友可以参考下
    2023-11-11
  • maven构建docker镜像push到镜像仓库方式

    maven构建docker镜像push到镜像仓库方式

    这篇文章主要介绍了maven构建docker镜像push到镜像仓库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • 详解利用nginx和docker实现一个简易的负载均衡

    详解利用nginx和docker实现一个简易的负载均衡

    本篇文章主要介绍了利用nginx和docker实现一个简易的负载均衡 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 如何利用Docker部署一个简单的springboot项目

    如何利用Docker部署一个简单的springboot项目

    这篇文章主要介绍了如何利用Docker部署一个简单的springboot项目,本文通过实例图文实例代码相结合给大家介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • Docker可视化面板Portainer的实现

    Docker可视化面板Portainer的实现

    Portainer是一个免费的容器管理工具,支持Docker环境的可视化管理,通过Portainer,用户可以轻松地在Windows或Linux容器中部署服务,大大简化了Docker容器的管理工作,感兴趣的可以了解一下
    2024-11-11

最新评论