必须创建并赋权宿主机目录,nginx用绑定挂载(:ro)实现热更新,mysql用具名卷保障数据持久,多容器共享时读写权限需严格分离。

你需要让Nginx容器里的网页文件修改后实时生效,同时确保MySQL容器重启后数据不丢,还要让两个容器共享同一份配置——这三件事必须用对数据卷类型和挂载方式才能稳住,错一步就可能丢数据或权限报错。
确认宿主机路径是否存在且可访问
执行 ls -ld /data/nginx/html 查看目录权限。如果返回 No such file or directory,说明路径根本不存在,【必须先创建目录并赋权,否则容器启动直接失败】。
用 sudo mkdir -p /data/nginx/html 创建完整路径,再运行 sudo chown -R 101:101 /data/nginx/html(Nginx容器内www-data用户UID/GID为101)。不改属主会导致容器内进程无写入权限,页面无法更新。
验证是否成功:运行 ls -ld /data/nginx/html,输出中应显示 drwxr-xr-x 2 101 101 开头。
三种挂载方式实操对比
同一需求下,不同挂载方式效果差异极大——开发调试要快,生产部署要稳,选错类型轻则热更新失效,重则数据库崩溃。
方法一:绑定挂载(适合开发环境)
命令:docker run -d --name nginx-dev -v /data/nginx/html:/usr/share/nginx/html:ro -p 8080:80 nginx。
这里用 :ro 指定只读,防止容器意外删改宿主机文件;【若省略 :ro,Nginx进程可能因权限问题无法启动】。
改完宿主机 /data/nginx/html/index.html,刷新浏览器立即生效——这是绑定挂载最核心的价值。
方法二:具名卷(生产环境首选)
第一步:创建卷 docker volume create mysql-data。
第二步:启动MySQL容器 docker run -d --name mysql-prod -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:8.0。
第三步:验证数据持久性——停掉容器 docker stop mysql-prod,再 docker rm mysql-prod,最后用同样命令重新 run,原库表全在。这是因为具名卷生命周期独立于容器。
注意:首次挂载空卷时,镜像中 /var/lib/mysql 的初始文件会自动复制进卷里;非空卷则跳过复制,直接挂载。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
方法三:匿名卷(仅用于临时缓存)
命令:docker run -d --name redis-cache -v /data/cache redis:7-alpine。
这个 -v /data/cache 没写宿主机路径,Docker自动在 /var/lib/docker/volumes/ 下生成随机ID目录存放数据。
缺点明显:你无法直接定位数据物理位置,也不能跨宿主机迁移;【一旦执行 docker volume prune,所有匿名卷连同数据被清空,不可恢复】。
多容器共享同一数据卷
场景:Nginx和PHP-FPM容器需共用代码目录,且都要能写日志。
先创建具名卷:docker volume create app-code。
启动PHP容器:docker run -d --name php-app -v app-code:/var/www/html -v /var/log/php:/var/log/php php:8.2-apache。
再启动Nginx容器:docker run -d --name nginx-app -v app-code:/usr/share/nginx/html:ro -v /var/log/nginx:/var/log/nginx nginx。
关键点:两个容器都挂载了 app-code 卷,但Nginx设为只读,PHP设为读写——这样既保证代码同步,又防止单点误操作破坏源码。
验证共享:在宿主机执行 echo "shared" > $(docker volume inspect app-code -f '{{ .Mountpoint }}')/test.txt,然后分别进入两个容器的挂载路径,都能看到该文件。
排查挂载失败的三把钥匙
容器启动后发现挂载目录为空?别急着重试,先查这三项:
第一,运行 docker inspect 容器名 | grep -A 10 Mounts,确认 Source 字段指向的路径真实存在且拼写无误——常见错误是把 /data/nginx 写成 /date/nginx。
第二,检查SELinux状态:getenforce 若返回 Enforcing,CentOS/AlmaLinux系统需加 --security-opt label=disable 参数或临时设为 permissive,否则挂载被拦截。
第三,查看卷权限:docker volume inspect 卷名 输出中 Mountpoint 路径的属主是否匹配容器内进程UID——比如MySQL容器用UID 999,而卷目录属主是root,就会拒绝写入。










