You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Docker容器中生成Composer的vendor文件夹并同步至宿主机

解决方案:容器生成vendor并同步到宿主机,同时保证服务正常

核心思路

  1. 容器构建阶段正常生成vendor目录,利用Docker缓存提升构建效率
  2. 容器启动时通过增量同步,将容器内的vendor同步到宿主机挂载目录(避免挂载卷直接覆盖容器内已生成的依赖)
  3. 确保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. 场景1问题解决:

    • 不再直接挂载vendor到容器的项目根目录,避免宿主机空目录覆盖容器内已生成的依赖
    • 通过rsync同步容器内构建好的vendor到宿主机目录,宿主机可实时获取同步后的文件
  2. 场景2问题解决:

    • 移除entrypoint中多余的sleep和等待循环,容器启动后立即同步并启动PHP-FPM,避免Nginx连接9000端口超时
    • 移除server服务中不必要的vendor挂载,Nginx仅需访问PHP脚本和静态文件,无需依赖目录

额外优化建议

  • 开发环境中:可在宿主机直接运行composer install,再将vendor挂载到容器,减少容器内同步操作
  • 生产环境中:无需同步vendor到宿主机,直接使用容器构建阶段生成的依赖即可,保证环境一致性

内容的提问来源于stack exchange,提问作者Javiloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:47:09