为啥尽管在图像构建期间通过 `composer global install` 安装了“drush”,但我无法从正在运行的 PHP 脚本中找到该工具?

Posted

技术标签:

【中文标题】为啥尽管在图像构建期间通过 `composer global install` 安装了“drush”,但我无法从正在运行的 PHP 脚本中找到该工具?【英文标题】:Why despite "drush" being installed via `composer global install` during image build, I cannot find the tool from within a running PHP script?为什么尽管在图像构建期间通过 `composer global install` 安装了“drush”,但我无法从正在运行的 PHP 脚本中找到该工具? 【发布时间】:2021-08-19 14:53:50 【问题描述】:

我正在 Docker 容器内开发一个 php Web 应用程序。在我的docker-compose.yml 文件中使用volumes:,我指定了一个本地目录,以便在容器被销毁后转储并保留生成的任何文件。

volumes:
  - ./docroot:/var/www/html

在我的Dockerfile,我RUN里面有一个安装命令行管理工具的命令:

RUN curl -sS https://getcomposer.org/installer | php && \
    mv composer.phar /usr/local/bin/composer && \
    ln -s /root/.composer/vendor/bin/drush /usr/local/bin/drush

RUN composer global require drush/drush:8.3.3 && \
    composer global update

当容器出现时,我可以使用docker-compose exec -it <container> bash 进入容器,一切正常。 drush 在我的路径中,我可以在整个容器中全局使用它来管理应用程序。

现在是奇怪的部分。我的应用程序的一部分是我必须从容器内的 PHP 脚本运行该命令,以帮助自动管理一些构建过程。

使用 php,我运行 exec('drush dbupdate', $output, $retval); $retval 返回退出状态 127,或者找不到命令并且 $output 为空。如果我切换 exec 以使用完整路径,我会得到退出状态 126。

如果我回到容器中,我可以正常运行该命令。请注意,所有其他 cli 命令都按预期与 exec 一起工作(lswhoami, 等,但 which drush 返回存在状态 1)

我错过了什么?为什么我手动可以毫无问题地使用它,但是 PHP exec() 却找不到呢? passthru()shell_exec() 和其他人的行为相同。

【问题讨论】:

你试过chmod +x /usr/local/bin/drush吗?可能是某些权限或不同的用户(您以 root 身份登录,但 php 从不同的用户运行) 啊,我们到了某个地方。 whoami 显示用户 www-data,但我想我是如何从上面安装的,它可以被所有用户使用。 是的,但事实并非如此。请参阅下面的答案以了解其原因。 :) 【参考方案1】:

composer global install 不会为所有用户“全局”安装命令,而是“全局”安装,就像“为所有项目”一样。

通常,这些包安装在用户执行命令的主目录中(例如~/.composer),如果它们在您的路径中可用是因为~/.composer/vendor/bin被添加到会话路径中。

但是当您运行composer global require(在构建映像时)或当您“登录”到正在运行的容器(使用exec [...] bash)时,涉及的用户是root。但是当您的 PHP 脚本运行时,它正在由另一个用户执行(大概是www-data)。对于那个用户,~/.composer 不包含任何内容。

也许不要使用composer安装drush,而是在构建映像时安装download the PHAR file directly or something like that,并将其放入/usr/local/bin

如果您使用 Drupal >= 8,推荐的安装 Drush 的方式不是作为“全局”依赖,而是作为“项目”依赖,以便安装适当的 drush 版本。这直接来自the docs:

建议使用 Composer 构建 Drupal 8 站点,并将 Drush 列为依赖项。该项目已经在其composer.json 中包含了 Drush。如果您的 Composer 项目还不依赖 Drush,请运行 composer require drush/drush 来添加它。完成此步骤后,您可以通过vendor/bin/drush联系Drush

【讨论】:

很想知道为什么 ln -s ... /usr/local/bin/drush 没有按预期工作。我确实是 .phar 文件的粉丝,但是这些天 Drupal 非常依赖作曲家,我犹豫要不要走这条路。如果我查看文件的权限,它们归 root:root 777 所有。我写的内容与 mv drush.phar /usr/local/bin/drush 有何不同? 我不知道作曲家安装是否为您提供了一个可以移动的独立 phar 存档。安装 drush 的推荐方法是通过 composer,但不是全局的,而是项目本地的(因此依赖项匹配)。如果您想在所有项目中使用相同的调用路径,请为此使用“drush-ops/drush-launcher”之类的东西。

以上是关于为啥尽管在图像构建期间通过 `composer global install` 安装了“drush”,但我无法从正在运行的 PHP 脚本中找到该工具?的主要内容,如果未能解决你的问题,请参考以下文章

尽管我有 Heroku 在构建期间找不到 package.json

如何使用 docker-compose 标记 docker 镜像

如何定义使用 docker-compose 构建的图像的名称

回形针:为啥尽管质量降低了,图像的大小却没有太大变化?

Docker 映像在 Windows/MVC 核心上构建的速度很慢

如何让 docker-compose 始终从新图像重新创建容器?