ComposerをDockerコンテナで動かす

# 0: はじめに

PHPでアプリケーションを作成の方には必須ともいえる、パッケージ依存管理ツール[Composer](https://getcomposer.org/)。
実は、Docker公式イメージとしてDockerHubに[composerイメージ](https://hub.docker.com/_/composer)が公開されています。
このイメージを使うと、ホストにComposerをインストールすることなく使い捨てのDockerコンテナ上でComposerを動かすことができます。
また、PHPはイメージに含まれるため、PHPのバージョンやインストール等を意識することなくコンテナを起動するだけでcomposerコマンドを走らせることが可能になっています。

本記事では、簡易なComposerの説明を行った後、Composer Dockerイメージの取得、そして、docker runでcomposerコマンドを走らせるところまで説明します。
また、最後の章でコマンドをもっと便利に扱うためのテクニックを紹介します。

## 0.1: 対象読者

- Dockerを既に導入済みの方
 - 本記事では本筋からずれるため、Dockerのインストールやdockerコマンドの説明は行いません
- Linux等のUnix環境をお使いの方
- [Composer](https://getcomposer.org/)を導入したい方
- Composer本体の環境構築に悩みたくない方

## 0.2: 今回使用した環境

- Mac (macOS Mojave v10.14.5)
- Docker CE (v18.09.2)
- [composer Docker image (v1.8.6)](https://hub.docker.com/_/composer)

# 1: [Composer](https://getcomposer.org/)について

[Composer](https://getcomposer.org/)とは、PHPパッケージの依存管理ツールです。
例えば、AというパッケージがBというパッケージを必要とする場合、手動ではAとB両方をインストールする必要があります。
さらに、インストールするバージョンも意識しないと、特定のバージョン同士の相性が悪い場合があるかもしれません。
アプリケーション開発に本来関係のない作業、パッケージのバージョン依存管理をしつつパッケージをインストールしてくれる、そんな賢いツールがComposerです。

Composerでパッケージをインストールする際に使うコマンドは次のコマンドです。
このコマンドを実行したディレクトリにvendorディレクトリが作成され、vendor配下にパッケージがインストールされます。

```
$ composer install
```

では、Composerは何を元にパッケージをインストールするのでしょうか？
ここで登場するのが、 `composer.json` と `composer.lock` です。
`composer.json` にはインストールしたいパッケージ名を記載します。
つまり、先の説明でいうAのパッケージ名とバージョンを記載します。
`composer.lock` にはインストールする全パッケージの名前とバージョンが記載されています。
つまり、先の説明でいうAとB両方のバージョンが記載されています。

以下に、 `composer.json` の例を示します。
これは、[PHPUnit](https://phpunit.readthedocs.io/ja/latest/index.html)をインストールするための `composer.json` です。

```json:composer.json
{
  "require-dev": {
    "phpunit/phpunit": "^8.2.5"
  }
}
```

PHPUnitをインストールしたいディレクトリに上の `composer.json` を配置し、そのディレクトリ上で `composer install` コマンドを叩くだけで必要なサブパッケージ(先の説明でいうB)も全てインストールしてくれます。
このとき、 `composer.lock` がそのディレクトリに存在しなければ、そのときインストールした全てのパッケージの名前とバージョンが記載される形で自動生成されます。
逆に、 `composer.lock` が存在すれば、そのときインストールされる全てのパッケージは `composer.lock` に記載されているバージョンになります。

つまり、毎回同じバージョンのパッケージをインストールしたい場合、同じ `composer.json` と `composer.lock` があれば事足りるというわけです。
例えば、複数の開発者で使用するパッケージのバージョンを統一したいときなどに有効です。

# 2: ComposerをDockerコンテナで動かす

## 2-1: Composerの[Docker公式イメージ](https://hub.docker.com/_/composer)を取得する

実際には、次のコマンドを実行するだけです。

```
$ docker pull composer
```

このコマンドにより、latestタグがつけられた `composer:latest` イメージを取得できます。
2019年7月15日現在、composerイメージは最新バージョンにlatestタグが付けられていますが、イメージ取得時にはバージョンを確認するようにしてください。
DockerHubでは、 `latest = 最新のバージョン` でないことがあるからです。

## 2-2: Composer install on docker container

まずは、 `composer.json` を置いているディレクトリに移動します。

```
$ ls
composer.json
```

移動したら、次のコマンドを実行するだけです。

```
$ docker run --rm -it -v $PWD:/app composer install
```

インストールが終われば、自動的にコンテナからデタッチされます。
また、 `--rm` オプションをつけることにより使い捨てコンテナとしてcomposerを実行することができます。
-iオプション(--interactive)は、ホストの標準入力をコンテナの標準入力につなげてくれます。
つまり、最後のinstallをコンテナ側に標準入力として送信してくれます
-tオプションは(--tty)、コンテナの標準出力をコンテナの標準出力につなげてくれます。
-vオプション(--volume)は `ホスト:コンテナ` 形式でボリュームマウントを指定します。
`composer` はイメージの指定で、その後の `install` は-iオプションによってコンテナに送信されるcomposerのコマンドです。

最終的に以下のようにvendorディレクトリが自動的に作られ、その配下にパッケージはインストールされています。
`composer.lock` も自動生成されています。

```
$ ls
composer.json  composer.lock  vendor
```

# 3: もっと便利にComposerコンテナを扱うためのテクニック

## 3-1: コマンドのエイリアスを貼る

`.bash_profile` や `.zshrc` に以下を記載

```
alias composer='docker run --rm -it -v $PWD:/app composer'
```

これにより、Dockerコンテナで動かさない通常の `composer` コマンドと同様に扱うことができます。
つまり、

```
$ composer install
```

の実行で、Dockerコンテナ上でcomposer installができるようになります。

# 4: まとめ

DockerコンテナでComposerを動かすことによって、Composer本体の環境構築を意識しなくてよくなりました。
さらに、使い勝手も通常のcomposerコマンドと変わりません。
ぜひ、コンテナを活用しましょう。

また、3章では、composerコマンドに `docker run` 命令のエイリアスを張り、これまでのcomposerコマンドと同様に扱う方法を紹介しました。
他にもっといい方法があればどしどしコメントをいただければと思います。