如何正确配置docker-compose让多容器共享volume且不覆盖镜像内置文件
解决方案
核心问题原因
你遇到的404确实是挂载逻辑导致的:Docker命名卷如果已经被初始化过(哪怕是空的),挂载到容器的/var/www路径时,会直接用卷内的内容覆盖路径下的文件,不会再同步镜像内的文件。同时你把composer update放在镜像构建阶段执行,此时运行时的volume还没挂载,生成的依赖只存在于镜像里,不符合你要求的在volume上执行的需求。
具体操作步骤
1. 调整php-fpm镜像构建逻辑
修改php-fpm/Dockerfile:
- 不要直接把代码拷贝到
/var/www,先存到镜像内的临时目录 - 移除Dockerfile里的
composer update命令 - 新增启动入口脚本,代码如下:
# 原有其他配置保持不变 COPY ./app/ /tmp/app/ COPY entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"]
在php-fpm配置目录下新增entrypoint.sh启动脚本:
#!/bin/sh set -e # 检查卷内是否已经存在项目文件,避免重复覆盖 if [ ! -f /var/www/artisan ]; then # 把镜像内临时存储的代码同步到挂载的volume中 cp -R /tmp/app/* /var/www/ # 生产环境建议用composer install替代update,配合composer.lock保证依赖版本一致 cd /var/www && composer install --no-dev --optimize-autoloader # 按需追加权限配置,比如storage/bootstrap目录写权限 chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache fi # 启动php-fpm主进程 php-fpm
2. 调整docker-compose.yml配置
保留原有的app-data命名卷配置,同时给nginx容器也挂载同一个卷,示例配置如下:
services: php-fpm: # 其他原有配置不变 volumes: - app-data:/var/www/ nginx: # 其他原有配置不变 volumes: # 给nginx只读挂载即可,满足静态资源和php文件读取需求,安全性更高 - app-data:/var/www/:ro # 声明全局共享的命名卷,所有服务挂载同一份 volumes: app-data:
3. 清理旧卷重新启动
因为之前的app-data卷已经有旧数据,需要先删除再启动才会走初始化逻辑:
# 注意:该命令会删除当前项目关联的所有卷,确认卷内无需要保留的数据后再执行 docker-compose down -v # 重新构建镜像并启动服务 docker-compose up -d --build
效果验证
启动完成后:
- php-fpm容器内
/var/www路径下的代码和依赖都存储在app-data卷中 - nginx和php-fpm读取的是同一份卷内的文件,不会出现404
- 后续重新构建镜像启动时,不会覆盖卷内已经存在的代码、用户上传的文件等数据
内容的提问来源于stack exchange,提问作者ossentoo
相关产品推荐
相关产品推荐

