DockerのhttpdイメージでWebサーバーを立てる（PHPも動かすよ！）

初めての投稿です！
仕事でコンテナを使う機会が増えてきたので、勉強も兼ねてPHPの動くWebサーバーをDockerで作っていきます。

今回は[Docker公式のhttpdイメージ](https://hub.docker.com/_/httpd)を利用してWebサーバーを立てます。
HTMLだけではなくPHPも動くように作っていきます。
(普通にPHPの動くサーバーであれば[Docker公式のPHPイメージ](https://hub.docker.com/_/php)の「php:<version>-apache」を使うとすぐに動かせそうな気がします。)

**なお、今回はDokerfileでの環境構築を行っていきますー。**

## 前提
- Dockerがインストールされていて、dockerコマンドが利用できる

## 作業環境
- Windows10
- Docker version 20.10.17, build 100c701
- Git Bash

## やってみよう！
### まずはディレクトリ構成
```:構成
.
├─ Dockerfile
├─ httpd.conf
└─ html
   └─ .htaccess
   └─ index.html
   └─ info
       └─ index.php
```

### Dockerfileを準備
```dockerfile:Dockerfile
FROM httpd:2.4.54

RUN apt-get update && apt-get install -y \
	php7.4 \
	libphp7.4-embed \
	php7.4-mbstring \
	php7.4-xml
RUN ln -s /usr/lib/apache2/modules/libphp7.4.so /usr/local/apache2/modules/libphp7.4.so

COPY ./html /usr/local/apache2/htdocs/
# COPY ./httpd.conf /usr/local/apache2/conf/
CMD httpd -D FOREGROUND
```
- `FROM` : Dockerイメージを指定する。
- `RUN apt-get update && apt-get install` : 最新バージョンのパッケージをインストールする。
- `\` : 処理を複数行に分ける。
- `RUN ln` : シンボリックリンクを作成する。
- `COPY` : プロジェクトファイル・フォルダ（コンテキスト）からコンテナイメージにコピーする。
- `CMD` : コンテナ実行時に実行するコマンドやファイルを指定する。
:::note info
このコマンドは後でコメントアウトをはずすのでそのままでOKです。
```
COPY ./httpd.conf /usr/local/apache2/conf/
```
:::

### HTMLとPHPファイルを用意
正直この辺のファイルの中身はなんでも大丈夫なので、好きなようにやっちゃって良きです。
```:html/index.html
<!DOCTYPE html>
<html lang="ja">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Top</title>
</head>

<body>
	<h1>Top Page</h1>
	<p>Hello!</p>
	<a href="/dynamic/">動的ページへ</a>
</body>

</html>
```
```:html/info/index.php
<?php
phpinfo();
?>
```
### .htaccessファイルを用意
PHPファイルの中でHTMLを記述できるようにする。
```:html/.htaccess
AddType application/x-httpd-php .php
```
### コンテナを操作
#### Dockerfileからイメージを構築
```
docker build -t httpd-php:1.1 -f Dockerfile .
```
- `-t`オプション : **名前**と**オプション**を`名前:タグ`の形式で指定します。
- `-f`オプション : Dockerfileの名前を指定します。パスを記載してもOK。
- 最後の`.`は記載ミスではなく**コンテクスト**を指定していて、指定したパス（URL）にあるファイル全てがビルド際に参照できます。（`COPY`命令等で利用する）

#### コンテナを作成して起動
`-d`オプションで**デタッチドモード**でコンテナを起動します。
つまりはバックグラウンドで実行しています。起動後コンテナの状態や操作をしたいので今回は利用しています。
`-p`オプションで**ポート**を指定しています。

```
docker run -d -p 8080:80 httpd-php:1.1
```
#### コンテナ一覧の表示
```
docker ps -a
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284251/688eb40f-e172-64ef-6b9a-a350c15acff5.png)
- `-a`オプション : 全てのコンテナを表示します。
デフォルトでは実行中のコンテナだけが表示されます。

#### コンテナを停止
```
docker stop 7583a7d6a2ed
```
- `docker ps -a`で取得したコンテナIDで対象のコンテナを指定します。

#### コンテナ一覧の一括削除
```
docker rm `docker ps -a -q`
```

### httpd.confファイルを用意
#### デフォルトファイルを取得
まずはデフォルトのhttpd.confを取得します。
```
docker cp 7583a7d6a2ed:/usr/local/apache2/conf/httpd.conf /path/to/folder/root/
```
Windowsであれば`C:/Users/`からのパスを記載すれば良いです。
取得したファイルをプロジェクトルートに配置します。
`docker cp <CONTAINER_ID>:<SRC_PATH> <DEST_PATH>`の要領で指定することで、コンテナとローカルの間でファイルやフォルダを コピーして出力します。
今回の場合はコンテナ側からローカルにファイルをコピーしています。

#### デフォルトファイルを編集
必要に応じてhttpd.confファイルを編集してください。
今回は下記の箇所を変更しました。
記述が多いので行ごとに記載をしていきます。（近い行はまとめるよ！）
```diff:httpd.conf
- #LoadModule ssl_module modules/mod_ssl.so
+ LoadModule ssl_module modules/mod_ssl.so
```
- `mod_ssl.so` : SSLを利用するために設定する。

```diff:httpd.conf
- #LoadModule rewrite_module modules/mod_rewrite.so
+ LoadModule rewrite_module modules/mod_rewrite.so
+ LoadModule php7_module modules/libphp7.4.so
```
- `modules/mod_rewrite.so` : リダイレクトや書き換えを行えるようにする。
- `modules/libphp7.4.so` : ApacheからPHPを利用できるようにする。

```diff:httpd.conf
- #
- AllowOverride None
+ #AllowOverride None
+ AllowOverride All
```
- `AllowOverride All` : .htaccessで設定できるディレクティブの種類を指定する。

```diff:httpd.conf
- <IfModule dir_module>
-     DirectoryIndex index.html
- </IfModule>
+ <IfModule dir_module>
+     DirectoryIndex index.html index.php
+ </IfModule>
```
- `AllowOverride All` : リクエスト（今回はURL）の最後が`/`で終わった場合に表示するファイルを設定する。

### もう一回コンテナの操作
httpd.confファイルが用意できたら、Dockerfileでコメントアウトしていた行の`#`を外します。
```diff
- # COPY ./httpd.conf /usr/local/apache2/conf/
+ COPY ./httpd.conf /usr/local/apache2/conf/
```
**再度コンテナの操作をしてもらえればPHPの動くWebサーバーの出来上がりです！！**

---
## おまけ
### コンテナを起動したけどアクセスできない（すぐにExitedになる）
こんな感じで`docker run`コマンドで起動後まもなくExitedとなりWebサーバーにアクセスできないような状況になることがありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284251/5d7dddea-52f5-3c30-2fc9-29f66cd593ad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284251/446a0bf5-1061-f560-840c-5f938a2a67ef.png)
そんな時は起動したコンテナ内で何かしら問題が起こっている可能性があるので、ログを出力してみると良きです。
```
docker logs <CONTAINER_ID>
```
（`<CONTAINER_ID>`は`docker ps -a`等で出力されるコンテナIDに置き換えてください。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284251/3d45e0b7-0ac8-384d-efcc-bdf4e1b2f4f2.png)
httpd.confでエラーが出ることがわかります！