DockerでMacに超絶シンプルなPHP&Apache環境を整える

# はじめに

PHP案件を頂いたため、MAMPでやるかぁーと思ったのですが、ふと、「MAMPの必要あるか…？:thinking:」となりました。

というのも、今回はDB使わないし、MacにはPHPもApacheも入ってるよなと思ったのです。

```terminal:Terminal
$ php -v
PHP 7.3.11 (cli) (built: Jun  5 2020 23:50:40) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies

$ httpd -v
Server version: Apache/2.4.41 (Unix)
Server built:   Jun  5 2020 23:42:06
```

うんうん入ってる。

ただし、ソースが動く本番環境のPHPバージョンは5系だったので、PHPのバージョンを切り替える必要がありました。

開発環境を整える方法として思いついたのは3つ。

1. HomebrewでPHPバージョンを切り替えて開発する
2. MAMPをちょっといじってPHPバージョンを切り替えて開発する
3. Dockerを建てちゃう

そんなにPHP案件が多いわけではないですが、ローカル環境をガチャガチャするのが嫌だし、LinuxライクにコマンドポチポチーでApache起動できる方が慣れているので、今回は3つめのDockerを採用することにしました。

# 前提

|環境|バージョン等|
|:-:|:-:|
|MacBook Pro|2019年モデル|
|OS|macOS Catalina|
|Docker Engine|v19.03.13|
|PHP|5.4|

# 1. Docker Desktopをインストールする

[公式サイト](https://www.docker.com/get-started)の**Download for Mac**を選択し、Docker Desktopをダウンロードします。

![スクリーンショット 2020-12-10 17.40.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924363/f4ddbbcd-2717-9d0c-8826-1ac4a53bcf3e.png)

Docker.dmgを実行し、インストールします。

インストール完了したら実行します。
実行後、パスワードを求められることがありますが、適宜入力してください。

実行すると上のメニューバーの右側にクジラさんが現れます。（ちっちゃくてすみません）↓
![スクリーンショット 2020-12-10 17.47.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924363/1d925b65-3491-50f3-e63b-b0526b9106b0.png)

試しにターミナルでコマンドを打ってみて確認します。

```terminal
$ docker version
Client: Docker Engine - Community
 Cloud integration: 1.0.2
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 16:58:31 2020
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:07:04 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
```

# 2. Dockerfileを作成してビルドする

## 2.1. Dockerfileの作成

Dockerfileを書いてイメージを作成します。

適当なディレクトリを作成し、Dockerfileを作成します。

```terminal
$ mkdir php5_apache

$ cd php5_apache

$ vim Dockerfile
```

[公式のDockerイメージ](https://hub.docker.com/_/php/)を拝借しちゃいましょう。
`php:<version>-apache`と記述することで、Apacheも含んだコンテナを建てられます。
今回使用するバージョンは*5.4*ですのでその通り記述します。

```:Dockerfile
FROM php:5.4-apache
```

## 2.2. ビルド

`docker build <Dockerfileのパス> -t <イメージ名>:<タグ名>`
でビルドをかけます。

ここでは、イメージ名は*php5_apache*、タグはバージョンとして*1.0*と指定しておきます。

`-t`: 名前とタグを指定するオプション

```terminal
$ docker build ./ -t php5_apache:1.0
```

ビルドできたか確認しましょう。

```terminal
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
php5_apache         1.0                 7246b9f23253        5 years ago         470MB
```

ちなみに、Docker Desktopのダッシュボードからも確認することができます。
![スクリーンショット 2020-12-10 18.31.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924363/d6e171ba-8c40-690d-9758-0d22cf323292.png)


# 3. コンテナを作成し、起動する

早速起動させていきましょう。

動かしたいソースは既に手元にあるので、マウントしちゃいます。

コマンドは以下の通り。
`docker run -d -p <ホスト側ポート>:<コンテナ側ポート> -v <ホスト側パス>:<コンテナ側パス> php5_apache:1.0`

今回使用したオプションの説明は以下。

- `-d`: デタッチドモードで起動する(バックグラウンド実行)
- `-p`: コンテナのポートをホスト側に公開する
- `-v`: ホスト側のディレクトリをコンテナにマウントする

```terminal
$ docker run -d -p 80:80 -v <作業ディレクトリ>:/var/www/html php5_apache:1.0
```

無事に起動できたか確認しましょう。

```terminal
$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED              STATUS              PORTS                NAMES
469f65bd6a4f        php5_apache:1.0     "apache2-foreground"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   recursing_hodgkin
```

# 4. ブラウザで確認

80番ポートで開いたのでポート指定なしで`localhost`をブラウザのアドレスバーに入力し開きます。
無事にPHP等が出力されていればOKです。

# 5. コンテナの開始と停止

コンテナを一度作成してしまえば、`docker start <コンテナIDまたはコンテナ名>`で起動、`docker stop <コンテナIDまたはコンテナ名>`で停止できます。

今回はコンテナ名でやってみます。
*recursing_hodgkin*と名付けられていましたので、それで停止、開始してみます。

```terminal
$ docker stop recursing_hodgkin
$ docker start recursing_hodgkin
```

# 6. コンテナにログインする

以下でrootでログインできます。
ちなみにOSはDebianです。

```terminal
$ docker exec -it recursing_hodgkin /bin/bash
```

出るときはおなじみの`exit`。

```terminal
# exit
```

# 7. おまけ

## 7.1. Apacheのエラー

ふとログを見てみるとなんかエラーっぽいログが吐かれていました。

```terminal
$ docker logs recursing_hodgkin
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Thu Dec 10 09:58:54.402679 2020] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.10 (Debian) PHP/5.4.45 configured -- resuming normal operations
[Thu Dec 10 09:58:54.402792 2020] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
```

「ドメイン名設定されてないよぉー困るよぉー:disappointed_relieved:」という内容です。
ご親切に「ServerNameディレクティブを設定しろ」と解決策まで書いてくれていますね。

多分設定しなくても問題ないんですが、エラーが残っているのが気持ち悪いので設定してあげます。

（私はCentOSばっかりいじってたので、DebianのApacheの設定ファイルとかどこ〜〜〜〜ってなりました。）

まずは、dockerにログイン。

```terminal
$ docker exec -it recursing_hodgkin /bin/bash
```

vimが慣れているので一応インストール。
apt updateしないとvimがインストールできなかったのでやむなくしてます。
Dockerfileに最初から書いとけばよかったと思いつつ……

```terminal:コンテナ内
# apt update
# apt -y upgrade
# apt install -y vim
# vim /etc/apache2/conf-enabled/httpd.conf
```

/etc/apache2/conf-enabled/*.confをconfigファイルとして読み込んでいるようなので、この中に記述していきます。

```conf:httpd.conf
ServerName localhost:80
```

Apacheサービス再起動。

```terminal
# /etc/init.d/apache2 reload
[ ok ] Reloading web server: apache2.
```

CentOSいじってると`systemctl restart httpd`で再起動なので、`service apache2 restart`で再起動したくなるんですが、これを実行したらコンテナも一緒にお亡くなりになられたので、上記コマンドを叩きます。

## 7.2. マルチバイト文字使えないんだが

**モジュール入れてないやろ。**

どこからかそんな声が聞こえてきました。

モジュールを入れて、

```terminal
# docker-php-ext-install mbstring
```

iniに追記し有効化します。

```ini:php.ini
extension=mbstring.so
```

恒例のapache再起。

```terminal
# /etc/init.d/apache2 reload
```

# 終わりに

私もDockerに明るいわけではないので、備忘録的に残しました。

phpのエラーログとか出すようにしたり、おまけに書いた部分をDockerfileに記述したり等、実際に開発始める上で躓いたところがあったので、そこらへんもあとで記事にしておきたいと思います。