LoginSignup
6
2

More than 3 years have passed since last update.

composer requireがメモリ不足で失敗しないために

Posted at

この記事の目的

パッケージ間の依存関係の解消に
メモリを多く消費するパッケージ ( 筆者が遭遇するケース:Larastan ) を、

デフォルトの設定 ( 通常使用時には上限128MB[php.ini],
Composer使用時には上限1.5GBまで拡張される ) のまま、

インストール(composer require)を試みると、
次のように標準エラー出力されます。

Fatal error: Allowed memory size of 1610612736 bytes exhausted
 (tried to allocate 4096 bytes)

Check https://getcomposer.org/doc/articles/
troubleshooting.md#memory-limit-errors 
for more info on how to handle out of memory errors

エラー文に書いてあるComposer公式URLにアクセスすると、
2種類の解決策が提示されていて、

1番目の解決策の方は、既に多くの先人達が
Qiitaにたくさん記事を残してくださっていました。

ただ、バージニア州に拠点を置くagileana社のブログ記事を読んで以来、
私は2番目の解決策の方が好ましく感じているので
そちらも推したいと思い執筆に至りました。

表現の誤りや「もっとこうしたら便利だよ」といったアドバイスなどありましたら、
教えて頂けると勉強になります。

筆者の実行環境

software version
Docker 19.03.13
Docker Compose 1.27.4
PHP 7.4

コンテナのベースイメージ ( FROM命令で指定したイメージ ) は、
php:7.4-fpm を使用してします。

なぜこの方法が好ましいと思ったか?

agileana社のブログ記事の中で
Symfonyを採用したプロジェクトに携わっていたFlynn氏が
記しているこの部分です。

My initial thought to fix this issue was to modify the memory_limit setting found in my PHP main configuration file,
but it will not only apply for the PHP CLI but to all the PHP process that I’m running (i.e. Local web server and Symfony commands.)

This is a side effect I was not willing to accept.

I started to research about this case and found a very straightforward solution to it and it will only apply to the Composer command you apply it to.

The solution is to use the COMPOSER_MEMORY_LIMIT environment variable, setting its value to -1. It can be added to the current Terminal session with

「PHPのメイン設定ファイル(php.ini)の
 memory_limitディレクティブの値を
 直接、無制限にしてしまうと、
 PHP CLIに適用されるだけでなく、
 ローカルWebサーバやSymfonyフレームワークのコマンドからの
 メモリ使用制限までも、無制限になってしまうため、
 そういった副作用を受けたくありません
。」

composerコマンド実行時のみ、メモリ上限を引き上げる方法を見つけました。

と書いてありますね。

ちなみに、私がメインで触っているLaravelも、
vendorディレクトリ下で動くたくさんのSymfonyで書かれたプログラムに
お世話になっていますから親近感がありますね。

変更方法

ディレクトリ構成はこうなっています。

$ tree -L 3

.
├── docker
│   ├── db
│   │   └── data
│   ├── nginx
│   │   └── default.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
└─── docker-compose.yml

コンテナは3つ

  • appコンテナ (PHP環境)
  • nginxコンテナ
  • dbコンテナ

[手順1] コンテナ内で使用しているcomposerのPATHを確認

$ which composer

/usr/bin/composer

[手順2] environmentキーに環境変数COMPOSER_MEMORY_LIMITを追加。

appコンテナ (PHP環境)の部分に追記。

docker-compose.yml
services:
  app:
    environment:
      - COMPOSER_MEMORY_LIMIT= -1 /usr/bin/composer
  • 値を-1にすると、無制限。
    • [OK] 略称表記 (例: 2G )
    • [OK] 数値表記 (例:2147483648 )

[手順3] docker-compose.ymlの変更を反映させるために再ビルドを実行。

docker-compose up -d --build app

そもそも何にそんなにメモリを使用しているのか知りたい

composer require --dev nunomaduro/larastan --profile -vvv
--profileオプション

タイムとメモリ使用量を表示する。

-vvvオプション

インストール時の挙動を詳細に表示する
(-vよりも、-vv、そして、-vvvと、vの数が増えると、
より詳しく表示してくれます。)

実行すると、このようになります。

root@79255afbc2bf:/var/www/html# composer require --dev nunomaduro/larastan --profile -vvv

Reading ./composer.json
Loading config file ./composer.json
Checked CA file /etc/ssl/certs/ca-certificates.crt: valid
Executing command (/var/www/html): git branch --no-color --no-abbrev -v
Reading /root/.composer/composer.json
Loading config file /root/.composer/composer.json
Reading /var/www/html/vendor/composer/installed.json
Reading /root/.composer/vendor/composer/installed.json
Running 1.10.13 (2020-09-09 11:46:34) with PHP 7.4.11 on Linux / 4.19.76-linuxkit

[9.2MiB/0.01s] Downloading https://repo.packagist.org/packages.json
[9.3MiB/0.87s] Writing /root/.composer/cache/repo/https---repo.packagist.org/packages.json into cache
[9.3MiB/0.87s] Reading /root/.composer/cache/repo/https---repo.packagist.org/p-provider-2013.json from cache
[12.6MiB/0.89s] Reading /root/.composer/cache/repo/https---repo.packagist.org/p-provider-2014.json from cache
[19.8MiB/0.93s] Reading /root/.composer/cache/repo/https---repo.packagist.org/p-provider-2015.json from cache
[31.7MiB/0.98s] Reading /root/.composer/cache/repo/https---repo.packagist.org/p-provider-2016.json from cache
[46.6MiB/1.05s] Reading /root/.composer/cache/repo/https---repo.packagist.org/p-provider-2017.json from cache
[68.9MiB/1.15s] Downloading http://repo.packagist.org/p/provider-2018%2481dd16ef8b70152a886f398fcf7d35c20870bf64605fbcf78e7fb9baac1f5ac2.json
.
.
.
(中略)
.
.
.
[860.0MiB/174.09s] Generating optimized autoload files
[866.5MiB/209.97s] > post-autoload-dump: Illuminate\Foundation\ComposerScripts::postAutoloadDump
[870.4MiB/210.14s] > post-autoload-dump: @php artisan package:discover --ansi
[870.4MiB/210.14s] Executing command (CWD): '/usr/local/bin/php' -d allow_url_fopen='1' -d disable_functions='' -d memory_limit=' -1 /usr/bin/composer' artisan package:discover --ansi

[870.4MiB/211.65s] Discovered Package: facade/ignition
[870.4MiB/211.65s] Discovered Package: fideloper/proxy
[870.4MiB/211.65s] Discovered Package: laravel/tinker
[870.4MiB/211.65s] Discovered Package: nesbot/carbon
[870.4MiB/211.65s] Discovered Package: nunomaduro/collision

[870.4MiB/211.65s] Package manifest generated successfully.
[867.2MiB/211.79s] 56 packages you are using are looking for funding.
[867.2MiB/211.79s] Use the `composer fund` command to find out more!
[867.2MiB/211.79s] Memory usage: 867.22MiB (peak: 1783.7MiB), time: 211.79s

root@79255afbc2bf:/var/www/html# 

無事に、インストールできました!! :tada:

(余談) ちなみに、Allowed memory size of 1610612736 bytes exhaustedって数字は何?

1,610,612,736 bytes 
= 1.5 * (2^30)
= 1.5 * (2^10) * (2^10) * (2^10)
= 1.5 * 1,024 * 1,024 * 1,024
= 1.5 GB

この記事の冒頭で触れた、
Composer使用時のメモリ上限の1.5GBを使い果たしてしまいました。。。
ということですね!

Composer使用時にメモリ上限が1.5GBまで引き上げられる資料の参照
Note: Composer internally increases the memory_limit to 1.5G.

まとめ

メモリリークやcomposerについて調べるとても良い機会になりました。

思いの外、長くなってしまいましたが
ご覧頂きありがとうございます。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2