📝

PHPUnit実行環境をDockerでサクッと構築!

2022/04/30に公開

はじめに

PHP単体でテストコードの練習がしたいな〜と思い、サクッとDockerでPHPUnitの実行環境を作りました。
Dockerについて勉強中のため、手順などをまとめてみます。
※何かあればご指摘ください・・・!

ソースはこちら
https://github.com/shun57/phpunit-docker

ディレクトリ構成

テスト対象とテストコードはsrc配下に配置します。
PHPUnitをただ試してみたい方は、上記のgithubからソースを取得してください。

├─ src/
│  ├─ tests/FunctionTest.php // テストコード
│  └─ function.php // テスト対象
├─ Dockerfile
└─docker-compose.yml

環境

PHP 8.0
PHPUnit 9.5
Docker Desktop 4.5.0
Docker 20.10.12
Docker Compose 1.29.2

DockerでPHPUnit環境を構築

DockerHubでイメージを選ぶ

基本的には以下の2パターンから選択することになると思います。

  1. PHP公式イメージにPHPUnitを入れる(composerなどを使って)
  2. PHPUnitイメージを探して構築する ex. phpunit/phpunit

今回は、PHPの実行環境にComposerでPHPUnitを入れるパターン1 を試してみたいと思います。

PHPの公式イメージのリファレンスを確認する

リファレンスに色々と記載されているので、目を通しておきます。

イメージ選択

PHPの公式イメージの中でさらに種類があるので確認します。
Image Variantsの章を確認すると、以下の種類を確認できます。
Webサーバーが梱包されているイメージもあります。
今回はテスト実行だけなのでphp:<version>-cliを使います。

  • php:<version>-cli
  • php:<version>-apache(PHPとApache)
  • php:<version>-fpm(PHPとPHP-FPM)
  • php:<version>-alpine(PHPとAlpine Linux)

バージョン選択

PHPの公式イメージのTagsから目的のイメージを探します。
今回はphp:8.0-cliを使うので検索して、あるかどうか確認します。
見つかったらベースイメージとして、Dockerfileを書きましょう。

Dockerfileの作成

Dockerfileの作成にはいくつかのアプローチがあると思います。
例えば、以下のような感じ。

①composerをイメージに含めて、コンテナ内でphpunitを入れる。phpunitもコンテナ内、もしくは外から実行する。
docker-entrypoint.sh[1]を作成し、phpunitのインストールやphpunitの実行も実施できるようにする。

②の方がスマートな感じもしますが、今回は①のパターンで、コンテナ内でphpunitのインストールとphpunitの実行したいと思います。

  1. FROMにベースイメージを指定します。
Dockerfile
FROM php:8.0-cli
  1. PHPUnitのインストールに必要なzipunzipをインストールします。
Dockerfile
RUN apt-get update && apt-get install -y \
    zip \ 
    unzip
  1. Composerをインストールします。

Composerの公式イメージを確認すると、トラブルシューティングの箇所に以下の記述があります。
Docker17.05以上の場合はマルチステージビルドというものが導入されており、こちらの記載のコマンドでComposerをイメージに含めることができます。
めっちゃ便利、、、
※マルチステージビルドについては他の記事をご参照ください。

私たちのイメージは、ホストにPHPランタイムをインストールしなくても、Composerをすばやく実行することを目的としています。コンテナ内のPHPバージョンに依存しないでください。Composerをベースイメージまたは本番イメージとして使用することを推奨したくないため、サポートされているPHPバージョンごとにComposerイメージを提供していません。
提案:
(最適)独自のビルドイメージを作成し、その中にComposerをインストールします。
注: Docker 17.05はマルチステージビルドを導入し、これを大幅に簡素化しました。
COPY --from=composer /usr/bin/composer /usr/bin/composer

Dockerfile
COPY --from=composer /usr/bin/composer /usr/bin/composer
  1. 最後に作業ディレクトリを設定します。今回は/appとしておきます。
Dockerfile
WORKDIR /app

以上でDockerfileは完成です。
最終系はこんな感じです。

Dockerfile
FROM php:8.0-cli

RUN apt-get update && apt-get install -y \
    zip \ 
    unzip

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

WORKDIR /app

docker-compose.ymlの作成

  1. versionの指定

docker-composeで使用するバージョンの定義のようです。
※ただし、最新のバージョンであるDocker Compose V2では不要のようです。
詳しくはこちらの記事が参考になりますので、紹介させていただきます。

https://zenn.dev/miroha/articles/whats-docker-compose-v2

docker-compose.yml
version: '3.9'
  1. serviceの指定

コンテナの定義をします。
テストソースをマウントして、コンテナでテスト実行できるようにします。
コンテナに入れるようにttyを設定します。

docker-compose.yml
services: # 各コンテナを定義
  php: # サービス名
    build: ./ # 構築時のオプションを指定、今回はDockerfileの場所
    container_name: phpunit # 任意のコンテナ名を設定
    tty: true # コンテナを起動し続ける
    volumes:
      - type: bind # バインドマウントをする(ホストとコンテナを同期)
        source: ./ # マウントするソースの場所(ホスト)
        target: /app # マウント先の場所

PHPUnitのインストールと実行、削除

Dockerfileのある作業ディレクトリ上にターミナルで移動し、コマンドを実行します。

コンテナの構築、起動

バックグラウンドで実行します。
コンテナが起動中であることを確認してください。

$ docker compose up -d

コンテナに入る

コンテナに入ってComposerを確認します。

$ docker container exec -it phpunit bash
// コンテナ内
~:/app# composer -V
Composer version 2.3.5 ~

ComposerでPHPUnitをインストール

~:/app# composer require --dev phpunit/phpunit

composer.jsonやvendorファイルがホスト側にも作成されます。

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

PHPUnitを実行

PHPUnitが実行できることを確認します。
私のgithubのソースを使っている場合は、1件失敗するようになっています。

~:/app# vendor/bin/phpunit src/tests --testdox

PHPUnit 9.5.20 #StandWithUkraine

Function
 ✔ Morning
 ✘ Evening
   │
   │ Failed asserting that two strings are identical.
   │ --- Expected
   │ +++ Actual
   │ @@ @@
   │ -'hello!'
   │ +'good evening!'
   │
   │ /app/src/tests/FunctionTest.php:17
   │

 ✔ Hello

Time: 00:00.311, Memory: 6.00 MB

Summary of non-successful tests:

Function
 ✘ Evening
   │
   │ Failed asserting that two strings are identical.
   │ --- Expected
   │ +++ Actual
   │ @@ @@
   │ -'hello!'
   │ +'good evening!'
   │
   │ /app/src/tests/FunctionTest.php:17
   │

FAILURES!
Tests: 3, Assertions: 3, Failures: 1.

コンテナの停止・削除

PHPUnitを実行するだけのコンテナなので、
利用が終われば削除して、また使いたい場合は実行します。

~:/app# exit
// コンテナの停止・削除
$ docker compose down 

終わりに

Dockerを実務で使うことがほとんどないので、
これだけでもかなり大変でした、、、
基本的なことは理解したので、個人でバリバリ使っていきたいと思います!

脚注
  1. ヘルパー・スクリプトと呼ばれるもので、コンテナの開始時にENTRYPOINTでシェルを実行できます。初回起動の時だけ何かしらのコマンドを実行したい場合などに利用するようです。 ↩︎

GitHubで編集を提案

Discussion