Docker挂载(Mount)

一种将主机文件系统上的目录或文件系统挂载到Docker容器内的方式,可以让容器访问主机上的文件系统,也可以让容器之间共享数据。

Docker支持两种挂载方式:

命名挂载
命名挂载使用预先定义的数据卷进行挂载。首先需要使用docker volume create命令创建一个数据卷,然后使用–mount或-v选项将数据卷挂载到容器中。例如:

docker volume create mydata
docker run --mount source=mydata,target=/app/data myimage:latest

上述命令创建了一个名为mydata的数据卷,并将其挂载到容器中的/app/data目录中
使用 -v 挂载时,如果宿主机上没有指定文件不会报错,会自动创建指定文件;当使用 --mount时,如果宿主机中没有这个文件会报错找不到指定文件,不会自动创建指定文件
因此上述命令等价于:

docker volume create mydata
docker run -v mydata:/app/data myimage:latest

docker创建的数据卷默认是共享卷,即:可以挂载到多个容器,并且在一个容器里面的改动,在其他容器也会有体现

docker volume create myvolume
 docker run -d --name my-container -v myvolume:/data mysql

但是会报错:

2023-11-25 23:05:49 2023-11-25 15:05:49+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
2023-11-25 23:05:49     You need to specify one of the following as an environment variable:
2023-11-25 23:05:49     - MYSQL_ROOT_PASSWORD
2023-11-25 23:05:49     - MYSQL_ALLOW_EMPTY_PASSWORD
2023-11-25 23:05:49     - MYSQL_RANDOM_ROOT_PASSWORD

这是因为 MySQL 镜像在启动时检测到数据库未初始化,并且没有设置 MySQL root 用户密码。MySQL 镜像要求在启动容器时提供 root 用户密码,以确保安全性。

你可以通过以下几种方式之一解决这个问题:

设置 root 用户密码: 在 docker run 命令中,使用 -e 选项设置环境变量 MYSQL_ROOT_PASSWORD 来指定 root 用户的密码。

docker run -d --name my-container -v myvolume:/data -e MYSQL_ROOT_PASSWORD=mysecretpassword mysql

将 mysecretpassword 替换为你想要设置的实际密码。

允许空密码: 如果你希望 root 用户没有密码,可以使用 -e 选项设置环境变量 MYSQL_ALLOW_EMPTY_PASSWORD。

docker run -d --name my-container -v myvolume:/data -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql

随机生成 root 用户密码: 如果你希望 MySQL 在每次启动时为 root 用户生成一个随机密码,可以使用 -e 选项设置环境变量 MYSQL_RANDOM_ROOT_PASSWORD。

docker run -d --name my-container -v myvolume:/data -e MYSQL_RANDOM_ROOT_PASSWORD=true mysql

创建两个容器并挂载同一个卷,就可以实现共享: docker exec -it my-container2 bash在一个容器里面修改卷内容,另一个容器也会有体现
在这里插入图片描述

匿名挂载

匿名挂载是一种将主机上的目录或文件系统挂载到容器内部的方式,不需要预先定义数据卷。可以使用–mount或-v选项指定要挂载的目录或文件系统。例如:

在这里插入图片描述

docker run -d --name my-container3 -v D:/temp_files/docker_file:/dockerfiles -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql将主机上的D:/temp_files/docker_file目录挂载到容器中的/docker_file目录中,然后就可以实现互通,任何一个目录的改动在另一个也会有相同的改动。

在使用挂载时,需要注意以下几点:

1.目标路径必须是容器内部的绝对路径。
2.如果要在多个容器之间共享数据,则需要使用相同的挂载路径和选项。
3.如果挂载了主机上的目录,则容器内的更改将反映在主机上,并且主机上的更改将反映在容器内。
4.如果挂载了数据卷,则数据将在容器停止和删除后仍然存在。
总之,使用挂载可以让容器访问主机上的文件系统,并可以在多个容器之间共享数据。

数据卷

Docker的数据卷是一种特殊的目录,可用于在容器和主机之间持久化和共享数据。它们允许容器中的数据在容器停止和删除后仍然存在,并允许多个容器共享同一卷,使用数据卷可以使容器中的数据持久化,并且可以在多个容器之间共享相同的数据。这使得容器更加灵活和可靠,同时也简化了容器的管理和部署。

使用数据卷有以下几个步骤:

创建数据卷:可以使用以下命令来创建数据卷:

docker volume create <volume-name>

将数据卷挂载到容器中:可以使用以下命令来挂载数据卷到容器中:

docker run -v <volume-name>:<container-path> <image-name>

其中,volume-name是数据卷的名称,container-path是容器中要挂载数据卷的路径,image-name是容器使用的镜像名称。

在容器中使用数据卷:可以在容器中的应用程序中使用挂载的数据卷。任何写入容器中挂载的路径的数据都将被持久化到数据卷中,并且在容器被删除时仍然存在。

共享数据卷:可以在多个容器之间共享数据卷。可以使用相同的数据卷名称和路径来挂载数据卷,从而使多个容器都能够访问相同的数据。

删除数据卷:可以使用以下命令来删除数据卷:

docker volume rm <volume-name>

如果数据卷当前正在被容器使用,则无法删除。要删除被容器使用的数据卷,必须先删除使用该数据卷的容器。

在Docker Compose中使用数据卷:

定义数据卷1(命名挂载)
在Docker Compose文件中,可以使用volumes关键字来定义数据卷。例如:

version: "3.9"
services:
  app:
    image: myapp:latest
    volumes:
      - mydata:/app/data
volumes:
  mydata:

上述代码定义了一个名为mydata的数据卷,并将其挂载到应用程序容器中的/app/data目录中。
定义数据卷2(匿名挂载)

version: "3"

services:
  db:
    image: mysql
    volumes:
      - /data/mysql:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: my-secret-pw

  web:
    build: .
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      DB_HOST: db
      DB_NAME: mydatabase
      DB_USER: root
      DB_PASSWORD: my-secret-pw

定义了两个服务:一个 MySQL 服务(名为 db),一个 Django 服务(名为 web)。我们还定义了两个 volumes,一个用于将本地的 /data/mysql 目录挂载到 MySQL 容器中的 /var/lib/mysql 目录上,另一个用于将当前目录(即 .)挂载到 Django 容器中的 /code 目录上。

在使用Compose时,如果没有手动创建数据卷,则Compose将自动创建它们。在数据卷的生命周期内,数据将保留在主机的文件系统中,并可以被多个容器共享。如果需要清除数据卷,则可以使用以下命令:

在运行 Docker Compose 时,我们可以使用如下命令:

docker-compose up

Docker Compose 会自动创建并启动两个容器,并将它们连接在一起。MySQL 容器中的数据会被保存到本地的 /data/mysql 目录中,而 Django 容器中的代码会被保存到本地的当前目录中。

docker-compose down --volumes

这将清除所有Compose中定义的数据卷。

数据卷的位置

在容器中,数据卷通常被挂载到容器的文件系统中的某个目录。Docker容器中的文件系统包括只读的镜像层和可写的容器层,数据卷属于容器层,可以被多个容器共享。Docker容器中挂载数据卷的路径通常是绝对路径,可以在启动容器时通过-v或–mount参数指定。

在主机上,Docker数据卷的位置取决于数据卷类型。Docker支持多种类型的数据卷,包括:

匿名卷
匿名卷是在Docker容器内部创建的卷,没有命名和标签。在主机上,匿名卷存储在Docker的数据目录下,通常是/var/lib/docker/volumes目录。

命名卷
命名卷是具有名称和标签的数据卷,可以在创建容器时手动创建或者在Docker Compose文件中定义。在主机上,命名卷也存储在Docker的数据目录下,但是路径包括了卷的名称和标签信息。例如,如果创建了一个名为mydata的数据卷,那么该卷在主机上的位置通常是/var/lib/docker/volumes/mydata/_data

绑定挂载
绑定挂载将主机上的目录或文件系统挂载到容器中,因此在主机上,挂载的位置就是绑定的目录或文件系统的位置。

挂载和数据卷

相比挂载,数据卷的优点是由于是 Docker 统一管理的,不存在由于权限不够引发的挂载问题,也不需要在不同服务器指定不同的路径;缺点是它不太适合单配置文件的映射。
和挂载一样,数据卷的生命周期脱离了容器,删除容器之后卷还是存在的。下次构建镜像时,指定卷的名称就可以继续使用了。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐