【问题标题】:Running composer install within a Dockerfile在 Dockerfile 中运行 composer install
【发布时间】:2018-03-28 22:26:52
【问题描述】:

我正在尝试 Dockerize 我的 laravel 应用程序。 该应用程序已经在 git 中构建,但我 .gitignore 我的供应商文件夹。 我添加了一个 Dockerfile,如下所示:

FROM php:7.1-fpm-alpine

RUN apk update && apk add curl && \
  curl -sS https://getcomposer.org/installer | php \
  && chmod +x composer.phar && mv composer.phar /usr/local/bin/composer

RUN apk --no-cache add --virtual .build-deps $PHPIZE_DEPS \
  && apk --no-cache add --virtual .ext-deps libmcrypt-dev freetype-dev \
  libjpeg-turbo-dev libpng-dev libxml2-dev msmtp bash openssl-dev pkgconfig \
  && docker-php-source extract \
  && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ \
                                   --with-png-dir=/usr/include/ \
                                   --with-jpeg-dir=/usr/include/ \
  && docker-php-ext-install gd mcrypt mysqli pdo pdo_mysql zip opcache \
  && pecl install mongodb redis xdebug \
  && docker-php-ext-enable mongodb \
  && docker-php-ext-enable redis \
  && docker-php-ext-enable xdebug \
  && docker-php-source delete \
  && apk del .build-deps

WORKDIR /var/www/html

COPY composer.json composer.lock ./
RUN composer install --no-scripts --no-autoloader

COPY . .
RUN chmod +x artisan

RUN composer dump-autoload --optimize && composer run-script post-install-cmd

CMD php artisan serve --host 0.0.0.0 --port 5001

当我构建时,这似乎工作得很好。我看到下载的依赖项,我看到在输出中生成了自动加载文件。但是,一旦构建完成,供应商文件夹实际上并不存在。我猜这一切都是在一个中间容器中完成的,然后被移除了?所以当我运行 docker-compose up 时,我得到: 致命错误:require():打开失败需要'/var/www/html/bootstrap/../vendor/autoload.php'

这个帖子似乎指出了这个问题 - 可能 - 但并没有真正提供解决方案:Composer install doesn't install packages when running in Dockerfile

【问题讨论】:

  • 尝试使用 COPY composer.json ./ 而不是 COPY composer.json composer.lock ./ (不要复制 composer.lock) 并有这一行 COPY 。 .以上作曲家安装
  • 复制。 .将复制整个目录,因此无论如何都会复制 composer.json 和 composer.lock 。为什么我不想复制锁定文件?这就是我想要安装的基础。
  • 你应该将 composer.lock 添加到你的 .dockerignore 中。请看:getcomposer.org/doc/…
  • 如果我这样做,那么我实际上是在运行作曲家更新。这不是我想要的。我不追求最新版本的依赖项,我想要 composer.lock 文件中的版本。目前,甚至没有创建供应商文件夹,所以我什么也没得到......
  • 你试过放 COPY 吗? .以上作曲家安装命令?

标签: docker composer-php docker-compose


【解决方案1】:

根据https://hub.docker.com/_/composer的建议

运行

WORKDIR /your/base/path
COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN composer install

【讨论】:

    【解决方案2】:

    您也可以使用official dockerhub composer 图像。

    这是一个多阶段构建示例,composer 首先在单独的容器中运行。生成的 /app/vendor 将复制到最终图像中您想要的任何位置。

    FROM composer as builder
    WORKDIR /app/
    COPY composer.* ./
    RUN composer install
    ...
    FROM php:7.1-fpm-alpine
    ...
    COPY --from=builder /app/vendor /var/www/vendor
    

    【讨论】:

    • 我认为这是一个更好的解决方案,因为它利用了图像的合成,而不是强迫我们单独安装作曲家
    • 啊,但它不适用于 OP 描述的挂载目录,太糟糕了
    【解决方案3】:

    我使用这个命令,它会生成供应商:)

    docker run --rm -it --volume $(pwd):/app prooph/composer:7.2 install --ignore-platform-reqs
    

    【讨论】:

    • 我唯一的问题是我想为新开发人员设置一个命令.....
    • 这正是医生所要求的!
    • 这无关紧要,要求 Dockerfile 实现,而不是命令行。
    【解决方案4】:

    如果您不想在 Dockerfile 中包含该命令,我们发现最简单的方法是将其添加到我们的 docker-compose 文件中:

    composer_installation:
      container_name: composer_installation
      image: composer
      volumes:
        - ./:/app
      command: composer install --ignore-platform-reqs
    

    更新有点慢,可能是和PHP容器同步的缘故。

    【讨论】:

    • 非常有用,因为您的基本映像可能不包含 curl 或 php。便携性的荣誉!
    • @Jérôme Gillard 我也可以将此配置用于生产吗?
    • 我这样做的唯一问题是在它完成安装后它会删除一些东西并且不能......你可以将它作为 sudo 运行以避免权限问题吗? Could not delete /app/vendor/composer/<hash>/<composer package>/Examples/templates
    • 容器在此之后立即退出,因此在尝试运行服务器时没有多大用处。
    【解决方案5】:

    这需要对 Docker 新手进行大量挖掘 :) 感谢@iurii-drozdov 用关于 docker-compose.yml 的评论为我指明了正确的方向。

    在我的 docker-compose.yml 中,我将主机工作目录挂载到 /var/www/html 中。这发生在构建之后。因此,composer 运行了安装,在构建时正确安装了所有依赖项,然后,在运行 docker-compose up 时,我将主机目录安装到容器中并清除所有这些更改。

    解决方案是在安装卷之后运行 composer install 。 只需在启动容器后执行该容器即可——运行 composer 和任何其他包管理器——然后最终运行 Web 服务器。

    但是,我找到了一个更简洁的解决方案。我将 Dockerfile 中的最终 CMD 更改为:

    CMD bash -c "composer install && php artisan serve --host 0.0.0.0 --port 5001"
    

    这将运行 composer install 并启动 web 服务器作为 docker-compose up 的最后一部分。

    感谢这里的解决方案:Docker - Execute command after mounting a volume

    【讨论】:

    • 您也可以在 docker-compose 中的容器声明下添加 command 关键字,如下所示: command: composer install && php artisan serve --host 0.0.0.0 --port 5001
    • 这是一个很好的解决方案,只要您希望供应商文件夹作为根目录
    • 如果是Lumen,没有php artisan serve,CMD会触发容器以状态0退出,有什么解决办法吗?
    • ENTRYPOINT 脚本是添加所有这些额外内容的好地方。
    • 是的,但请记住,在 CMD 中安装依赖项的版本是不同的解决方案,其中依赖项不是您的 Docker 映像的一部分。现在,它们将在部署期间的每次 docker 运行时被拉取,这可能会导致部署错误。
    猜你喜欢
    • 2017-10-01
    • 2023-03-14
    • 2017-02-12
    • 2016-12-13
    • 2022-12-12
    • 2020-04-10
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    相关资源
    最近更新 更多