问题

docker volume 可以使我们在启动 docker 容器时,动态的挂载一些文件(如配置文件), 以覆盖镜像中原有的文件。但是,挂载一个主机上尚不存在的文件夹或者文件到容器中会擦除容器中原有的文件。

解决方案

具名挂载

使用具名挂载 (named volumes) 可以在不覆盖容器内容的情况下进行挂载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: '3.4'

volumes:
templates:
driver: local
driver_opts:
type: none
o: bind
device: ${PWD}/templates

services:
yarp:
container_name: yarp
image: kamasylvia/yarp
restart: always
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:80;http://+:443
ports:
- 80:80
- 443:443
volumes:
- templates:/app/templates:ro
- ./configs:/app/configs:ro
- ./logs:/app/logs
- ~/.aspnet/https:/root/.aspnet/https:ro
- ~/.microsoft/usersecrets:/root/.microsoft/usersecrets:ro

Warning

未在 Docker for Windows/macOS 上测试过。

Info

  1. 具名挂载中的宿主目录不可以用相对路径,因此使用 ${PWD} 替代相对路径。
  2. 必须先在宿主机上手动新建需要映射的 templates 文件夹。
  3. 停止服务时需要同时卸载具名挂载: docker-compose down -v

挂载文件夹权限问题

按照上面的配置运行 docker-compose up -d 后成功挂载了 templates 文件夹,

但是这时候 templates 下的文件都是 docker 的 root 用户创建的,宿主机普通用户只有只读权限,无法修改。

这也是为什么我们挂载的是 templates 而不是 configs。之后需要用户在宿主机上新建 configs 文件夹和其中的配置文件,并把 templates 中的 配置文件内容 手动复制黏贴过去。

Warning

普通用户对 templates 文件夹和其下文件只有只读权限,不可直接复制文件到 configs 文件夹。因此只能复制内容到剪切板再黏贴到新文件中。

直接挂载 configs 文件夹

直接挂载 configs 文件夹会造成普通用户无法修改配置。

解决方法:

  1. 临时使用 sudo 提升权限。(简单粗暴,十分有效)
  2. 官方实践:
    1. 解决 Docker 数据卷挂载的文件权限问题 - 简书
    2. docker - sudo or gosu - spacewander - SegmentFault 思否

参考资料