基于本文回答

播面 播面

文解图解播客视频,多维讲透八股文
0
评论

如何在多个不同的容器之间共享同一个数据卷或宿主机目录?

在 Docker 中,在多个不同的容器之间共享同一个数据卷(Volume)或宿主机目录是非常常见且实用的需求(例如:一个容器写日志,另一个容器收集日志;或者多个 Web 容器共享静态资源)。

主要有以下两种方式来实现共享:


方式一:使用 Docker 命名数据卷(Named Volumes)—— 推荐

这是 Docker 官方推荐的方式。数据卷由 Docker 引擎管理,具有更好的移植性、性能和安全性。

1. 命令行(CLI)实现

首先,创建一个命名数据卷:

bash
docker volume create my-shared-volume

然后,在启动多个容器时,都将这个数据卷挂载到它们各自的目录中:

  • 启动容器 A(向卷中写入数据):
    bash
    docker run -d --name container_a -v my-shared-volume:/app/data alpine sh -c "while true; do echo 'Hello from A' >> /app/data/log.txt; sleep 5; done"
  • 启动容器 B(从同一个卷中读取数据):
    bash
    docker run -d --name container_b -v my-shared-volume:/app/read_data alpine sh -c "tail -f /app/read_data/log.txt"

注意:容器 A 挂载到了 /app/data,容器 B 挂载到了 /app/read_data,它们指向的是同一个物理存储,路径可以不同。

2. Docker Compose 实现(最常用)

如果你使用 Docker Compose,定义共享卷非常简单:

yaml
version: '3.8'

services:
  web:
    image: nginx:alpine
    volumes:
      - shared-assets:/usr/share/nginx/html

  app:
    image: node:alpine
    volumes:
      - shared-assets:/usr/src/app/public

volumes:
  shared-assets: # 在最外层定义共享卷

2. 方式二:挂载同一个宿主机目录(Bind Mounts)

如果你希望直接在宿主机上看到和修改这些文件,可以直接将宿主机的某个绝对路径挂载到多个容器中。

1. 命令行(CLI)实现

假设宿主机目录为 /home/user/shared_dir(确保该目录已存在):

  • 启动容器 A
    bash
    docker run -d --name container_a -v /home/user/shared_dir:/data1 alpine sh -c "touch /data1/file_from_a.txt"
  • 启动容器 B
    bash
    docker run -d --name container_b -v /home/user/shared_dir:/data2 alpine sh -c "ls /data2"

2. Docker Compose 实现

yaml
version: '3.8'

services:
  service_a:
    image: alpine
    volumes:
      - /home/user/shared_dir:/app/data
    command: tail -f /dev/null

  service_b:
    image: alpine
    volumes:
      - /home/user/shared_dir:/app/backup
    command: tail -f /dev/null

3. 进阶技巧:只读挂载(Read-Only)

在多容器共享数据时,为了安全起见,通常只有一个容器负责写入,其他容器负责读取。你可以将读取端的容器设置为“只读”挂载。

在挂载路径后面加上 :ro 即可:

  • 命令行
    bash
    docker run -d --name reader_container -v my-shared-volume:/data:ro alpine
  • Docker Compose
    yaml
    services:
      reader:
        image: alpine
        volumes:
          - shared-assets:/data:ro # ro 表示 read-only

总结与选择

方案 优点 缺点 适用场景
命名数据卷 (Volume) 1. Docker 管理,跨平台兼容性好
2. 性能更好
3. 方便备份和迁移
在宿主机上不容易直接定位到具体的文件路径(默认在 /var/lib/docker/volumes/ 下) 容器间的数据传递、数据库持久化、不需要人工频繁修改宿主机文件的场景。
绑定挂载 (Bind Mount) 1. 宿主机路径直观,方便人工直接修改和查看文件 1. 依赖宿主机的目录结构,移植性差
2. 可能引入权限问题(UID/GID 不一致)
开发环境、需要读取宿主机上的配置文件或源代码、收集日志。