如果使用 Laravel 并且 Docker 容器启动失败,要执行 composer install,请运行 docker-compose run

简而言之

要想不使用 docker-compose up 来启动容器,而是执行特定命令,可以运行 docker-compose run <容器名称> <命令>,而不是使用 docker exec。

发生的错误

在使用Laravel时,出现了无法启动Docker容器的问题。

$ docker-compose up
# 中略
my_container | 
my_container | Warning: require(/var/www/my-app/vendor/autoload.php): failed to open stream: No such file or directory in /var/www/my-app/artisan on line 18
my_container | 
my_container | Fatal error: require(): Failed opening required '/var/www/my-app/vendor/autoload.php' (include_path='.:/usr/local/lib/php') in /var/www/my-app/artisan on line 18
my_container exited with code 255

本文中的错误是由于未执行composer install引起的,但本文将解决此问题。

前提知識:关于Docker和卷的挂载。

如果使用 Docker,通常情况下源代码是放在容器之外的。这样你可以在容器内部使用 vim 或者 vscode 等编辑器来编辑源代码,而不需要进入容器。现在,为了将其与容器关联起来,你可以在 docker-compose 中添加一个名为 “volumes” 的项,来挂载存储库。

services:
  my_container:
    # 中略
    volumes:
      - type: bind
        source: ./my-app
        target: /var/www/my-app

现在,重要的是在docker-compose内(即在容器启动时)能够挂载卷,但是在Dockerfile中(即在构建时)不能挂载本地文件夹。

 

在设置Dockerfile中的卷挂载时,不能指定主机上的目录。

这样一来,我们在构建时进行 composer install,将其结果反映在本地文件中就需要一点技巧。为了避免这种情况发生,我们决定将 composer install 放在容器的首次启动时而不是构建时进行。

解决方案 (jiě jué àn)

首先,构建容器。

docker-compose build my_container

下面是对该句的一个中文本地化的重新表述:
接下来,在初次启动容器之前,使用docker-compose run命令进行composer install操作,然后再使用docker-compose up命令启动容器。

docker-compose run composer install

最后,启动容器。使用-d参数可以在后台启动。

docker-compose up

我能够成功启动容器。我想可能可以通过相同的方法来处理Python(pip install)或Node.js(npm install或yarn install)的情况。

有没有更好的方法?

如果是个人开发的话,可能以上情况没有问题。但是,我们可以考虑是否可以创造更好的环境。

改善方案1:确保在执行docker-compose up时必定执行composer install。

COPY ./my-startup-script.sh /usr/local/bin/my-startup-script.sh
RUN chmod +x /usr/local/bin/my-startup-script.sh
CMD ["my-startup-script.sh"]
composer install
apache2-foreground # サーバーを起動

这真是方便又简单呢。(我想,不用准备脚本文件,直接用 bash -c 也行。)

 

当然,你也可以在docker-compose.yml中添加command选项。

 

不使用挂载供应商目录的改进方案2。

通过不挂载 vendor 目录(或 node_modules 目录等),可以防止在主机上错误地执行 composer install,确保该操作仅在容器内部进行。毕竟,这些文件只对容器有效,因此确保在容器外部不可见似乎是合理的。这个技巧被称为 Volume Trick。

根据以下文章的表述,可以通过在一个音量中创建另一个音量来实现。

 

或者,似乎只需指定一个空的容量即可。

services:
  my_container:
    # 中略
    volumes:
      - type: bind
        source: ./my-app
        target: /var/www/my-app
      - type: volume # ボリュームマウント
        target: /var/www/my-app/node_modules # 除外するディレクトリ

 

而且更好的是,这将传承构建时的 vendor/ 目录。

如果你在自己提供的 Dockerfile 中执行 npm install等操作,会导致删除镜像内的node_modules文件夹。为了避免这种情况,你可以准备一个命名卷,将node_modules存储在其中,这样就不再同步到主机上了。

 

如果你使用的是 VSCode,可能需要进行一些额外的配置和解决一些问题,可能需要自己解决。在这种情况下,你可以尝试搜索 “Volume Trick” 等解决方案。

 

只需要一种选择,用中文将以下内容进行释义:
オチ

首先,Docker Compose启动时容器出现错误终止是不正常的,这个问题是由于Dockerfile中的CMD被错误地覆盖导致的。在被覆盖之前的命令可以通过在Docker Hub上搜索原始镜像来确认。

广告
将在 10 秒后关闭
bannerAds