目录
目标
掌握绑定挂载、临时挂载的常用命令。理解绑定挂载、数据卷、临时挂载之间的区别。
官方文档
绑定挂挂载(Bind mounts)
简介
官方定义
Bind mounts have been around since the early days of Docker. Bind mounts have limited functionality compared to volumes. When you use a bind mount, a file or directory on the host machine is mounted into a container. The file or directory is referenced by its absolute path on the host machine. By contrast, when you use a volume, a new directory is created within Docker's storage directory on the host machine, and Docker manages that directory's contents.
The file or directory does not need to exist on the Docker host already. It is created on demand if it does not yet exist. Bind mounts are very performant, but they rely on the host machine's filesystem having a specific directory structure available. If you are developing new Docker applications, consider using named volumes instead. You can't use Docker CLI commands to directly manage bind mounts.
官方示意图
翻译
- 与数据卷相比,绑定挂在功能有限。
- 绑定挂载要用主机上的绝对目录引用,如果目录不存在,则会按需求创建。而使用数据卷时,不需要引用主机上的绝对目录,Docker会创建目录并管理这个目录中的内容。
- 绑定挂载性能高,但推荐优先考虑使用数据卷,因为绑定挂载依赖于主机文件系统中存在特定的目录结构(官方的示意图很好地体现了这一点)。
- Docker命令不能直接管理绑定挂载。
基本创建方法
方法一:用mount参数创建。前提条件:引用的主机目录必须存在,否则报错。
#source:主机目录
#target:容器目录
#type:挂载类型为绑定
docker run -d -p 8848:80 --name nginx --mount type=bind,source=/opt/data/,target=/usr/share/nginx/html nginx
方法二:用v参数创建。如果主机目录不存在则会自动创建目录。
#-v前面的目录表示主机目录,如果这个目录不存在则会自动创建。
#-v后面的目录表示容器目录
docker run -d -p 5601:80 --name nginx2 -v /opt/data/html:/usr/share/nginx/html nginx
控制读写权限(默认有读写权限)
方法一:用mount参数创建。
#readonly:创建只读权限
docker run -d -p 8848:80 --name nginx --mount type=bind,source=/opt/data/,target=/usr/share/nginx/html,readonly nginx
#readonly=true:创建只读权限
docker run -d -p 8848:80 --name nginx --mount type=bind,source=/opt/data/,target=/usr/share/nginx/html,readonly=true nginx
#readonly=false:创建读写权限
docker run -d -p 8848:80 --name nginx --mount type=bind,source=/opt/data/,target=/usr/share/nginx/html,readonly=false nginx
方法二:用v参数创建。
#rw:创建读写权限
docker run -d -p 8848:80 --name nginx -v /opt/data/html:/usr/share/nginx/html:rw nginx
#ro:创建只读权限
docker run -d -p 8848:80 --name nginx -v /opt/data/html:/usr/share/nginx/html:ro nginx
验证:进入容器内部,尝试修改被映射的目录中的内容。发现修改失败,说明只读挂载生效。
为什么绑定挂载不适合做数据库持久化
- 绑定挂载不支持跨容器共享,而数据卷支持。
- 绑定挂载直接暴露宿主机文件系统,使得容器和宿主机之间的隔离性降低,可能导致数据泄漏或安全隐患。数据卷更好地支持容器的隔离性和数据的独立性。容器与宿主机的文件系统的隔离,使得数据管理更为简单和安全。
- 绑定挂载依赖主机文件系统,需要关注主机文件的权限、存储空间等问题。
- 数据卷提供了更为丰富的数据管理功能,如自动备份、恢复、数据迁移等,这些功能在绑定挂载中是无法实现的。
为什么绑定挂载更适合做热部署
两者都可以实现热部署,但是:
- 绑定挂载将主机目录直接映射到容器的文件中,使得修改主机文件可以实时更新到容器文件中。
- 数据卷侧重安全和持久化,实时同步不如绑定挂载优秀。数据卷中的文件进行修改甚至可能需要手动操作来确保变更被及时应用到容器中。
临时挂载(tmpfs mounts)
简介
官方将没有将临时挂载归为绑定挂载之类,而是将其与绑定挂载并列。虽然他们之间的命令只在type值上有所区别,但是数据存储方式完全不同,这在官方文档和示意图中都能有明确的说明。
官方文档
As opposed to volumes and bind mounts, a tmpfs mount is temporary, and only persisted in the host memory. When the container stops, the tmpfs mount is removed, and files written there won't be persisted.
翻译
与卷和绑定挂载不同,tmpfs挂载是临时的,只持久化在主机内存中。当容器停止时,tmpfs挂载将被删除,写入其中的文件将不会被持久化。
基本创建方法
#这三条的命令的区别在于指定容器目录使用的参数不同,实际上它们是等价的。
docker run -d -p 8848:80 --name nginx --mount type=tmpfs,destination=/usr/share/nginx/html nginx
docker run -d -p 5601:80 --name nginx2 --mount type=tmpfs,dst=/usr/share/nginx/html nginx
docker run -d -p 3306:80 --name nginx3 --mount type=tmpfs,target=/usr/share/nginx/html nginx
验证临时挂载的生命周期
第一步:进入Nginx容器内部,修改Nginx的主页,并访问主页。
docker exec -it nginx2 /bin/bash
cd /usr/share/nginx/html/
echo '<h1>111</h1>' > index.html
第二步:重启容器,再次访问Nginx首页,发现首页已经没有了。
最佳实践
注意
- 临时挂载的数据存储在内存中,如果容器创建期间没有给设定内存阈值,则该容器会有耗尽服务器内存的风险。所以我们如果使用临时挂载,最好在创建容器时设定容器内存阈值和挂载内存阈值。
- 容器内存包含进程、各种文件系统、挂载内存。比如设定容器内存为100兆,挂载内存20兆,则容器中其他消耗内存的操作可用内存是80兆。
案例
给Nginx容器的首页目录设定20兆内存阈值,容器总内存设定100兆内存阈值。
查看容器内存使用情况
查看挂载内存
#进入容器后执行查看内存的命令
df -h
如图所示,挂载内存使用了4K。
数据卷&绑定挂载&临时挂载的区别
特性/方式 | 绑定挂载(Bind Mount) | 数据卷(Volume) | 临时挂载(Tmpfs Mount) |
适用场景 | 开发热部署、日志文件系统。侧重开发和测试阶段。 | 数据库持久化、MQ中间件。侧重生产阶段。 | 铭感数据比如密码、认证数据、密钥,避免写入到磁盘中 |
数据存储位置 | 宿主机指定目录 | Docker 管理的卷位置 | 内存(RAM) |
数据持久化 | 依赖宿主机目录 | 数据卷的具体存储路径由Docker决定,通常位于宿主机的Docker文件系统中(如 /var/lib/docker/volumes/),所以不依赖于宿主机的直接目录结构。 | 数据不持久化,容器停止后丢失。 |
跨容器共享 | 不支持(除非使用同一宿主机目录) | 支持跨容器共享 | 不支持 |