🗂

Composer のアップグレードに学ぶ Dockerfile FROM 命令のタグ指定

2021/04/26に公開

はじめに

あるプロジェクトで Laravel 環境を Docker で構築して開発しています。その中で、個人的にちょっとした学びがあったのでまとめてみました。

docker -v
Docker version 20.10.5, build 55c4c88

開発環境のコンテナ

下記がローカルで動かしているコンテナの Dockerfile です。

FROM php:7.4-fpm-alpine

COPY php.ini /usr/local/etc/php/

ARG TZ

COPY --from=composer /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
RUN composer config -g repos.packagist composer https://packagist.jp
RUN composer global require hirak/prestissimo
RUN docker-php-ext-install pdo_mysql opcache

Dockerfile の詳細

マルチステージビルド

名前の通り、複数のビルドステージに分割してイメージのビルドを行います。この手法を用いることのメリットとしては、ビルド用のイメージとランタイムとして動くアプリケーションのイメージを分離できることイメージサイズの軽量化などが挙げられます。

こちらの Dockerfile では、公式の Composer イメージを利用しています。

COPY --from=composer /usr/bin/composer /usr/bin/composer

マルチステージビルドについて詳しく言及しないので、知らなかったという方は是非下記の記事をご一読ください。

https://qiita.com/minamijoyo/items/711704e85b45ff5d6405

hirak/prestissimo

続いて導入しているライブラリについてです。
このライブラリは、composer でのパッケージインストールを並列で行ってくれるものです。それによりパッケージインストールの高速化が狙えるので、毎回入れるようにしています。

今回の問題

上記の Dockerfile をビルドすると下記のようなエラーが出ます。

docker build --no-cache .

..

 => ERROR [stage-0 5/6] RUN composer global require hirak/prestissimo                                                             1.2s
------
 > [stage-0 5/6] RUN composer global require hirak/prestissimo:
#9 0.300 Changed current directory to /composer
#9 1.195
#9 1.199
#9 1.199   [RuntimeException]

#9 1.199   No composer.json present in the current directory (./composer.json), this may be the cause of the following exception.
#9 1.199
#9 1.199
#9 1.201
#9 1.201   [InvalidArgumentException]
#9 1.201   Could not find package hirak/prestissimo.
#9 1.201
#9 1.201   Did you mean this?
#9 1.201       hirak/prestissimo
#9 1.201
#9 1.201
#9 1.201 require [--dev] [--dry-run] [--prefer-source] [--prefer-dist] [--fixed] [--no-suggest] [--no-progress] [--no-update] [--no-install] [--no-scripts] [--update-no-dev] [-w|--update-with-dependencies] [-W|--update-with-all-dependencies] [--with-dependencies] [--with-all-dependencies] [--ignore-platform-req IGNORE-PLATFORM-REQ] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [--sort-packages] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--apcu-autoloader-prefix APCU-AUTOLOADER-PREFIX] [--] [<packages>]...
#9 1.201
------
executor failed running [/bin/sh -c composer global require hirak/prestissimo]: exit code: 1

原因

タグの指定

ぱっと見、前述した hirak/prestissimo がない見つからないというエラーです。

噛み砕いていくと --from=composer では、タグによるバージョン指定を行なっていません。デフォルトだと latest というタグが Docker Hub より pull されるため、今回 composer:latest すなわち 2 系の公式 composer イメージが docker pull されていました。(PHP では指定しているのに・・・。)

Composer v2

composer 2 系でのアップデートで劇的にパフォーマンスが改善されました。ここでも詳細は割愛します。下記の記事に分かりやすくまとめてありました。

https://qiita.com/ucan-lab/items/289009ffe5bb417c808e

ここでのポイントとしては、composer v2 では、パッケージの並列インストールが可能になったということです。すなわち hirak/prestissimo をインストールする必要がなくなりました。(composer v2 には未対応。)

https://github.com/composer/composer/pull/5293/files

対処方法

対処する方法としては 2 つ考えられます。

1. composer v2 にアップグレード

単純に composer v2 にしてしまうという方法です。その場合は Dockerfile で hirak/prestissimo をインストールしている箇所を削除しておきましょう。

また、今後のことも考えるとタグも明示的に指定してあげておくのが良いでしょう。

FROM php:7.4-fpm-alpine

COPY php.ini /usr/local/etc/php/

ARG TZ

- COPY --from=composer /usr/bin/composer /usr/bin/composer
+ COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
RUN composer config -g repos.packagist composer https://packagist.jp
- RUN composer global require hirak/prestissimo
RUN docker-php-ext-install pdo_mysql opcache

2. Docker イメージにタグを明示的に指定

composer v2 に気軽にアップグレードしてしまうのが怖い場合は、対処方法 1. のうちタグの指定だけ行うという方法です。もしかしたら依存関係により動かなくなってしまう可能性もあるので 1 系で固定してしまうのも応急処置としてはありではないでしょうか。

COPY --from=composer:1.10 /usr/bin/composer /usr/bin/composer

まとめ

最後に本記事のまとめを書いて終わります。

  • Dockerfile の FROM 命令ではタグを明示的に指定するのを忘れない。
  • composer は 2 系を積極的に導入していきたい。
  • hirak/prestissimo はとても優秀なライブラリ。1 系を使うなら導入必須。

参考にさせていただいたサイト

https://qiita.com/lighthawk/items/dc9ba08206b02ffca8a0
https://docs.docker.jp/engine/userguide/eng-image/dockerfile_best-practice.html

GitHubで編集を提案

Discussion