マルチステージビルドを使ってDockerにcomposerをインストールする

PHPのパッケージ管理システムであるcomposerをDockerにインストールする際にマルチステージビルドを使うといい感じだったのでメモ。

まずは普通にインストール

composerの公式ドキュメントに従い、PHPを使ってインストールしていく getcomposer.org

  1. composerのインストーラー(PHPファイル)をダウンロード

  2. ダウンロードしたインストーラーのハッシュ値とオリジナルのファイルを比較してファイルの破損・改ざんが無いかチェック

  3. インストーラーを実行し、composerをインストール

  4. インストーラーを削除

Dockerfileに記述するとこんな感じ

FROM php:7.4-cli

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

しかしこれだと、composerのバージョンが変わるとハッシュ値が変更されてしまい、インストールが失敗してしまう。 となると、毎回composerのバージョンが上がる度にハッシュ値を書き換える必要がある。

マルチステージビルドを使ったインストール

composerの公式のDockerイメージがあるので、マルチステージビルドを使用して以下のように書くことができる、

hub.docker.com

FROM php:7.4-cli

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

COPY --from=composer /usr/bin/composer /usr/bin/composerの部分で、composerのイメージの中から/usr/bin/composerだけをPHPコンテナの中にコピーでき、毎回バージョンが上がる度にハッシュ値を書き換えなくても良くなる。

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

Docker 17.05からの機能で、docker buildを複数のビルドにして実行することができる。

matsuand.github.io

これによって、ビルドするだけの一時的なイメージを作るステージ、デプロイ用のイメージ作るステージを分離することができる。

これで何が嬉しいかというと、例えばビルド済みのイメージから必要なファイルだけをデプロイ用のイメージに取り込むことによってデプロイ用のイメージのサイズを削減することが出来たりする。

goのプログラムをビルドして試してみる

hello worldを表示させるためのプログラムを以下のように記述

hello.go

package main

import "fmt"

func main() {
    fmt.Println("hello world")
}

作成したプログラムをビルドするステージ、プログラムを実行するステージに分けて以下のようにDockerfileを記述する。

# ビルドするだけの一時的なイメージを作るステージ
FROM golang:alpine AS build-stage
COPY . /work
WORKDIR /work
RUN go build hello.go

# ビルド済みのバイナリファイルを実行するステージ
FROM busybox
COPY --from=build-stage /work/hello /usr/local/bin/hello
ENTRYPOINT ["/usr/local/bin/hello"]

COPY --from=build-stageとすることで、直前のステージで作り出された生成内容を、単純に新たなステージにコピーしている。 こうすることで、プログラム実行するイメージには、直前のステージでビルドしたバイナリファイルだけをコピーすることができ、無駄のないイメージを作成できることができる。

参考

qiita.com

qiita.com