如何在Docker容器中生成Composer的vendor文件夹并同步至宿主机
解决方案:容器生成vendor并同步到宿主机,同时保证服务正常
核心思路
- 容器构建阶段正常生成
vendor目录,利用Docker缓存提升构建效率 - 容器启动时通过增量同步,将容器内的
vendor同步到宿主机挂载目录(避免挂载卷直接覆盖容器内已生成的依赖) - 确保PHP-FPM服务优先启动,不被同步操作阻塞
步骤1:修改API服务的Dockerfile
FROM php:8.2-fpm RUN apt-get update && apt-get install -y \ unzip rsync \ && docker-php-ext-install pdo pdo_mysql WORKDIR /var/www/html/ # 先复制composer配置文件,利用构建缓存,避免代码变更重复执行composer install COPY ../backend/composer.json ../backend/composer.lock ./ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install -vvv --no-dev --optimize-autoloader # 复制项目其他文件 COPY ../backend . # 添加entrypoint脚本 COPY ../backend/entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] # 保留PHP-FPM默认启动命令 CMD ["php-fpm"]
步骤2:编写正确的entrypoint.sh脚本
#!/bin/bash # 增量同步容器内的vendor到宿主机挂载目录 if [ -d "/var/www/html/vendor" ] && [ -d "/var/www/html/host_vendor" ]; then rsync -a --delete /var/www/html/vendor/ /var/www/html/host_vendor/ fi # 立即启动PHP-FPM服务 exec "$@"
说明:用rsync替代cp,仅同步变更文件更高效;无需等待逻辑,构建阶段已生成完整vendor。
步骤3:修改docker-compose.yml配置
version: '3.8' services: api: build: context: ../ dockerfile: backend/Dockerfile container_name: api restart: unless-stopped working_dir: /var/www/html/ volumes: - ../backend/src/:/var/www/html/src/ - ../backend/public/:/var/www/html/public/ # 挂载宿主机vendor目录到容器临时目录,用于同步 - ../backend/vendor/:/var/www/html/host_vendor/ depends_on: - mariadb frontend: image: nginx:1.25-alpine container_name: frontend restart: always ports: - 3001:80 volumes: - ../frontend:/usr/share/nginx/html command: ["nginx", "-g", "daemon off;"] mariadb: image: mariadb:latest container_name: mariadb-container environment: MYSQL_ROOT_PASSWORD: your_root_password MYSQL_DATABASE: your_database_name MYSQL_USER: your_database_user MYSQL_PASSWORD: your_database_password ports: - "3306:3306" volumes: - mariadb-data:/var/lib/mysql server: image: nginx:1.25-alpine container_name: my-nginx-server restart: always ports: - 8000:80 volumes: - ../backend/src/:/var/www/html/src/ - ../backend/public/:/var/www/html/public/ - ./nginx:/etc/nginx/conf.d depends_on: - api volumes: mariadb-data: driver: local
关键问题修正说明
场景1问题解决:
- 不再直接挂载
vendor到容器的项目根目录,避免宿主机空目录覆盖容器内已生成的依赖 - 通过
rsync同步容器内构建好的vendor到宿主机目录,宿主机可实时获取同步后的文件
- 不再直接挂载
场景2问题解决:
- 移除entrypoint中多余的
sleep和等待循环,容器启动后立即同步并启动PHP-FPM,避免Nginx连接9000端口超时 - 移除server服务中不必要的
vendor挂载,Nginx仅需访问PHP脚本和静态文件,无需依赖目录
- 移除entrypoint中多余的
额外优化建议
- 开发环境中:可在宿主机直接运行
composer install,再将vendor挂载到容器,减少容器内同步操作 - 生产环境中:无需同步
vendor到宿主机,直接使用容器构建阶段生成的依赖即可,保证环境一致性
内容的提问来源于stack exchange,提问作者Javiloper
相关产品推荐
相关产品推荐

