LoginSignup
245
213

More than 3 years have passed since last update.

Docker に Composer をインストールするベストプラクティス(と解説)

Posted at

Docker に Composer をインストールする際,Composer のバージョンアップのたびにハッシュ値を書き換えるのが面倒だったので,何か解決策はないかと調べていたところこちらの記事を発見しました。
正直これだけでいいじゃんという話ですが,内容が大変ミニマルでしたので,解説を交えて記事にさせていただきました。

結論

Dockerfile に以下を追記するだけで OK 。

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

ただし multi-stage builds (マルチステージビルド) を使用するため,Docker のバージョンは >=17.05 が必須です。

以下で解説します。

メジャーな方法(Composer 公式)

Composer 公式 のインストール方法を Dockerfile に記述するのが一般的かと思います。

例:PHP-FPM に Composer をインストールしたイメージを作る Dockerfile

FROM php:7.3-fpm

RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
  && php composer-setup.php \
  && php -r "unlink('composer-setup.php');" \
  && mv composer.phar /usr/local/bin/composer

この方法の問題点

上記の方法の4行目内のハッシュ値が問題です。

php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

このハッシュ値は Composer はバージョンアップごとに変更されるので(上記は2019/09/30現在),そのたびに Dockerfile も変更しなければなりません。

めんどうです。

解決法

Docker 公式の Composer イメージ を使用します。
Docker 17.05 から導入されたマルチステージビルドを使えば非常にシンプルに記述できます。
(すべて Docker 公式の Composer イメージのページの DESCRIPTION に記載されています)

  • (optimal) create your own build image and install Composer inside it.
    Note: Docker 17.05 introduced multi-stage builds, simplifying this enormously:
COPY --from=composer /usr/bin/composer /usr/bin/composer

以下の :1.8.6 のようにタグでバージョン指定もできますし,常に最新がよければタグなしもしくは :latest を付ければ OK です。

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

マルチステージビルドとは?

公式ドキュメント

With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.

簡単にいうと,ひとつの Dockerfile で複数のビルドができ,各ビルドの段階で必要な部分だけコピーして(残りは破棄される),最終的に使用したいベースイメージにペーストできる機能です。

例:golang をビルドしたバイナリだけを Alpine Linux イメージにコピーして起動する

# golang をビルド
FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

# 上でビルドしたバイナリだけを Alpine Linux イメージにコピー・起動
FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

さらに,イメージからコピーするだけであれば,下記のように簡略化できます。

例:Nginx のベースイメージ内の nginx.conf だけコピーしてくる

COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

解決法の具体例

前述した PHP-FPM の例は以下のように書き直せます。

before (再掲)

FROM php:7.3-fpm

RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
  && php composer-setup.php \
  && php -r "unlink('composer-setup.php');" \

after

FROM php:7.3-fpm

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

参考

謝辞

参考にさせていただいた記事「Dockerにcomposerをインストールする方法の正解」の hanhan 様に感謝いたします。

245
213
2

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
245
213