20230111更新:优化部分描述,减少歧义
初学docker的时候,遇到这么一个事
学习实验目标:
创建一个简单的docker容器,运行nginx,并且使配置文件目录,项目根目录映射到宿主机,实现持久存储
当时的做法:
docker run -idt -e "TZ=Asia/Shanghai" \
--name nginx_test \
-v /root/docker/nginx_test/conf:/etc/nginx \
-v /root/docker/nginx_test/logs:/var/log/nginx \
-v /root/docker/nginx_test/html:/usr/share/nginx/html \
-v /root/docker/nginx_test/cert:/etc/nginx/cert \
-p 80:80 \
-p 443:443 \
--restart=always \
nginx
当时遇到的问题:
容器退出,日志报错,nginx.conf配置文件找不到
docker exec 进容器内查看,确实/etc/nginx目录是空的
回到宿主机/root/docker/nginx_test/conf查看,也是空的
当时的猜想:
因为做了目录映射,所以宿主机空的目录导致容器内目录也为空,容器内运行的应用缺少了文件自然无法正常运行。只要将原本需要的文件放到对应的目录,即可解决问题。
当时的补救:
- 使用同版本的镜像,再创建一个nginx容器 “nginx-new”,并且不做任何映射或修改
- 使用docker cp命令将nginx-new中的/usr/share/nginx/html 、/var/log/nginx、/etc/nginx 三个目录拷贝到nginx-test对应的映射目录,填补原先空缺的文件
- docker start nginx-test
当时的结果:
nginx-test容器启动正常,后续使用也正常。
但是事情并没有那么简单
- 导致容器内目录被覆盖成空目录的原因?
所谓的映射其实是将宿主机的目录挂载到了容器内,容器内原来目录里的文件没有被删除。 - 如何让容器内文件或目录不被“覆盖”
像之前docker cp补全文件的方法,不是长久之计,因为这样做往往会跟着出现文件权限的问题。
所以用 - -mount 选项更合适。
- - volume和- - mount的比较
对比项 | - - volume 或 -v | - - mounttype=bind |
---|---|---|
如果主机路径不存在 | 自动创建 | 命令报错 |
能够使用的type类型 | 只能是bind volume | 可以指定bind volume或者volume或者tmpfs |
- - mount用法
使用- - mount默认type=bind
–mount source=[volume名称],destination=[容器内路径]
–mount type=bind,source=[绝对路径],destination=[容器内路径]
bind mount 和 volume 的区别
对比项 | bind mount | volume |
---|---|---|
Source位置 | 用户指定 | /var/lib/docker/volumes/ |
Source为空 | 覆盖dest为空 | 保留dest内容 |
Source非空 | 覆盖dest内容 | 覆盖dest内容 |
Source种类 | 文件或目录 | 只能是目录 |
可移植性 一般 | (自行维护) | 强(docker托管) |
宿主直接访问 | 容易(仅需chown) | 受限(需登陆root用户)* |
示例
#启动Nexus示例
docker run -d \
-p 8443:8081 \
--name nexus \
-e INSTALL4J_ADD_VM_PARAMS="-Xms1024m -Xmx1024m -XX:MaxDirectMemorySize=2703m -Djava.util.prefs.userRoot=${NEXUS_DATA}/javaprefs" \
--mount source=nexus-data,destination=/nexus-data \
sonatype/nexus3
参考文献:
https://blog.csdn.net/sch0120/article/details/106292036