Docker:更改存储Docker卷的文件夹

25

我在我的 Ubuntu EC2 上使用Docker容器托管一个应用程序。 db 数据和 upload 数据存储在卷 CaseBook-data-dbCaseBook-data-uploads 中,这些卷是使用以下命令创建的:

docker volume create --name=CaseBook-data-db
docker volume create --name=CaseBook-data-uploads

通过 docker-compose 文件附加的卷:

version: '2'
services:
    mongo:
        container_name: "CaseBook-db"
        restart: always
        image: mongo:3.2.7
        ports:
            - "27017"
        volumes:
            - data_db:/data/db
        labels:
            - "ENVIRONMENT_TYPE=meteor"

    app:
        container_name: "CaseBook-app"
        restart: always
        image: "meteor/casebook"
        build: .
        depends_on:
            - mongo
        environment:
            - MONGO_URL=mongodb://mongo:27017/CaseBook
        ports:
            - "80:3000"
        volumes:
            - data_uploads:/Meteor-CaseBook-Container/.uploads
        labels:
            - "ENVIRONMENT_TYPE=meteor"
volumes:
     data_db:
        external:
            name: CaseBook-data-db
     data_uploads:
        external:
            name: CaseBook-data-uploads

我需要将这些docker卷存储在主机的不同文件夹中(例如 /home/ubuntu/data/)。如何更改docker卷的存储文件夹?或者有更好的方法吗?谢谢。


使用本地持久化的Docker插件帮助我解决了这个问题。感谢BMitch提供的答案。 - DimonVersace
2个回答

33

命名卷将存储在Docker的文件夹(/var/lib/docker)中。如果您想在特定的主机文件夹中创建卷,请使用带有以下语法的主机卷:

命名卷将存储在 Docker 的文件夹(/var/lib/docker) 中。如果您想在特定的主机文件夹中创建卷,请使用以下语法的主机卷:

docker run -v /home/ubuntu/data/app-data:/app-data my-image

或者从你的Compose文件中:

version: '2'
services:
    mongo:
        container_name: "CaseBook-db"
        restart: always
        image: mongo:3.2.7
        ports:
            - "27017"
        volumes:
            - /home/ubuntu/data/db:/data/db
        labels:
            - "ENVIRONMENT_TYPE=meteor"

    app:
        container_name: "CaseBook-app"
        restart: always
        image: "meteor/casebook"
        build: .
        depends_on:
            - mongo
        environment:
            - MONGO_URL=mongodb://mongo:27017/CaseBook
        ports:
            - "80:3000"
        volumes:
            - /home/ubuntu/data/uploads:/Meteor-CaseBook-Container/.uploads
        labels:
            - "ENVIRONMENT_TYPE=meteor"

使用主机卷(host volumes),镜像内的任何卷内容都将被主机文件夹的确切内容覆盖,包括主机文件夹的UID。空的主机文件夹不会像空命名卷一样从镜像中初始化。UID映射往往是使用主机卷最困难的部分。


编辑:从下面的评论中可以看到,如果您需要作为主机卷的命名卷,则有一个local persist volume plugin列在Docker插件列表上。安装插件后,您可以创建指向主机文件夹的卷,并具有以下功能:即使删除命名卷后,主机目录仍然存在。插件的示例用法包括:

docker volume create -d local-persist -o mountpoint=/data/images --name=images
docker run -d -v images:/path/to/images/on/one/ one
docker run -d -v images:/path/to/images/on/two/ two

他们还包括了一个带有以下卷示例的v2组合文件:

volumes:
  data:
    driver: local-persist
    driver_opts:
      mountpoint: /data/local-persist/data

在过去一个月里,我了解到的另一个选项是使用本地卷驱动器的挂载选项手动创建绑定挂载。这类似于docker中的主机卷,但有以下不同之处:

  • 如果目录不存在,则尝试使用命名卷指向绑定挂载启动容器将失败。对于主机卷,docker会将其初始化为空目录,所有者为root。
  • 如果目录为空,则命名卷将使用映像位置上的内容来初始化绑定挂载,包括文件和目录所有权/权限。而对于主机卷,则不会初始化主机目录内容。

要将命名卷创建为绑定挂载,可以提前创建它:

docker volume create --driver local \
  --opt type=none \
  --opt device=/home/user/test \
  --opt o=bind \
  test_vol

使用 docker run 命令,可以通过 --mount 实现:

docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
    foo

或者在一个Compose文件中,您可以使用以下命令创建具名卷:

volumes:
  data:
    driver: local
    driver_opts:
      type: none
      o: bind 
      device: /home/user/test 

如果需要使用命名卷功能,我更倾向于使用本地驱动程序的命名卷,而不是第三方驱动程序local-persist。


1
但是有没有一种方法可以使用命名卷,但是具有相同的逻辑呢? - DimonVersace
2
至少就我所知,不能使用默认命名卷来实现这一点。你可以添加其他卷驱动程序,例如local persist,来支持此功能。 - BMitch
1
@ivantalalaev,主机卷是Docker术语中绑定挂载的另一种称呼。https://success.docker.com/KBase/Different_Types_of_Volumes - BMitch
1
@Vinciuz 它会传递给挂载系统调用。类型表示文件系统类型,比如ext4或nfs,但是在绑定挂载中,没有类型。 - BMitch
1
@teeeeee 这是一个绑定挂载(你会在 mount 中看到目录已经被挂载)。它不是数据的副本,而是同一目录的第二个文件系统路径,除了跟踪卷定义的一些 JSON 元数据之外,没有使用额外的磁盘空间。 - BMitch
显示剩余5条评论

4

使用内置的驱动程序是另一种本地方式:

docker volume create --opt type=none --opt device=/home/ubuntu/data/ --opt o=bind data_db

以下是使用DimonVersace示例,其中data_db在docker-compose中声明为外部命名卷,/home/ubuntu/data/是主机上的文件夹。


1
为什么这个解决方案不太出名?我已经使用了多年,没有发现任何缺点。 - Roemer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接