docker-laravel の Docker 構成をちゃんと理解する【Dockerfile 編 - Nginx】


@ucan-lab さんの [docker-laravel](https://github.com/ucan-lab/docker-laravel) の環境をちゃんと理解するための記事

今回は Dockerfile の Nginx 編です。

[docker-compose 編](https://qiita.com/tkek321/items/9c0c5cec1dc349c67f5f)
[Dockerfile 編 - PHP](https://qiita.com/tkek321/items/5d7714d7170bbf379c11)

# Dockerfile

https://github.com/ucan-lab/docker-laravel/blob/main/infra/docker/nginx/Dockerfile

```dockerfile:dockerfile
# --- ① ビルドイメージの指定 ---
FROM node:16-alpine as node
FROM nginx:1.20-alpine
# ------
# ② メタデータを追加
LABEL maintainer="ucan-lab <yes@u-can.pro>" 
# ③ デフォルトのシェルをオーバーライド
SHELL ["/bin/ash", "-oeux", "pipefail", "-c"]
# ④ 環境変数を設定
ENV TZ=UTC
# ⑤ イメージ上に任意のコマンドを実行
RUN apk update && \
  apk add --update --no-cache --virtual=.build-dependencies g++

# --- ⑥ COPY 命令 ---
# node command
COPY --from=node /usr/local/bin /usr/local/bin
# npm command
COPY --from=node /usr/local/lib /usr/local/lib
# yarn command
COPY --from=node /opt /opt
# ------

# ⑦ Nginx の設定ファイルをコピー
# nginx config file
COPY ./infra/docker/nginx/*.conf /etc/nginx/conf.d/

# ⑧ 作業ディレクトリを指定
WORKDIR /work/backend
```

[Dockerfile のコマンド](https://qiita.com/tkek321/items/5d7714d7170bbf379c11#dockerfile-%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89) については Dockerfile 編 - PHP を参照

# ① ビルドイメージの指定

https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/

- Dockerfile 内に複数の FROM 命令をかける
- 各 FROM 命令から新しいビルドステージが開始される
- イメージ内に生成された内容、一方から他方にコピーすることができる
- PHP の Dockerfile で [Composer をインストール](https://qiita.com/tkek321/items/5d7714d7170bbf379c11#-composer-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)する時にもマルチステージビルドを使っている
    - この時は直前のイメージじゃなくて、別のイメージから composer をコピーしてきている
    - [外部イメージの「ステージ」としての利用](https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/#use-an-external-image-as-a-stage)


### `FROM node:16-alpine as node`

- Docker Hub から node のイメージを持ってきている
    - https://hub.docker.com/_/node/
- [as 構文](https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/#name-your-build-stages)でビルドステージに名前をつけている
- 別のビルドステージで使用することができる
- 名前をつけただけでこのビルドステージは終了
- [alpine](https://qiita.com/ryuichi1208/items/6020cfabc92bd8153654) は Linux ディストリビューション

### `nginx:1.20-alpine`

- nginx のイメージを取得
    - https://hub.docker.com/_/nginx


## ② メタデータを追加

`LABEL maintainer="ucan-lab <yes@u-can.pro>" `

- [PHP の Dockerfile と同じ](https://qiita.com/tkek321/items/5d7714d7170bbf379c11#-%E3%83%A1%E3%82%BF%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E8%BF%BD%E5%8A%A0)

- メタデータの設定のみ動作に影響はなし

## ③ デフォルトのシェルをオーバーライド

`SHELL ["/bin/ash", "-oeux", "pipefail", "-c"]`

- [PHP の Dockerfile と同じ](https://qiita.com/tkek321/items/5d7714d7170bbf379c11#-%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%92%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89)

- デフォルトのシェルを今回は bash じゃなくて、ash に変更している
    - alpine のイメージは [ash](https://qiita.com/yutachaos/items/56dd7ea09d7e2b0d9173) を使ってるらしい


## ④ 環境変数を設定

`ENV TZ=UTC`

- OS（Debian） のタイムゾーンを UTC に設定している


## ⑤ イメージ上に任意のコマンドを実行

`RUN apk update && \
  apk add --update --no-cache --virtual=.build-dependencies g++`

- `\` ワンライナーで実行してイメージのレイアを軽くしている
    - [PHP の Dockerfile と同じ](https://qiita.com/tkek321/items/5d7714d7170bbf379c11#-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E4%B8%8A%E3%81%AB%E4%BB%BB%E6%84%8F%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C)

### `apk update`

- apk は ` Alpine Linux package management`の略
- Alpine のパッケージマネージャー
    - https://blog.kasei-san.com/entry/2020/08/25/084430
    - https://wiki.alpinelinux.org/wiki/Package_management#Update_the_Package_list


- パッケージの最新リストを取得
- おそらく、 [apt-get update](https://qiita.com/tkek321/items/5d7714d7170bbf379c11#apt-get-update)と似たような仕組みになってるんだろうな

### `apk add --update --no-cache --virtual=.build-dependencies g++`

- `apk add g++`
    - `g++` をインストールしている
    - https://pkgs.alpinelinux.org/package/v3.4/main/x86/g++
    - GNU C++ standard library and compiler
    - ちょっと何のためにあるのかわかってない
        - 試しに、丸っと削除削除して動かしてみたけど、 `make test` までは通った

- `--update`
    - [apk --updateという引数はない](https://qiita.com/mtgto/items/149248dac031a451be02) らしい
        - 要するに `--update-cache の省略形` らしい
    - [--update-cache](https://wiki.alpinelinux.org/wiki/Package_management#Update_the_Package_list)
        - 他の apk コマンドの前にまず apk update を実行するのと同じ効果が得られる

    - 前の `apk update` コマンドはなくてもいいのかも？


- `--no-cache`
    - ダウンロードされたパッケージは `/var/cache/apk` にキャッシュされるらしい
    - 不要なキャッシュでイメージのサイズが大きくならないようにしている

- `--virtual=.build-dependencies`
    - インストールした複数のパッケージと依存関係を一つの仮想パッケージとして名前をつけて保存
    - 今回は、`.build-dependencies` って名前をつけている
    - パッケージを削除するときに名前単位で削除したりできるらしい
    - 今回は `g++` だけだからなくてもいいのかも？

## ⑥ COPY 命令

```Dockerfile
# node command
COPY --from=node /usr/local/bin /usr/local/bin
# npm command
COPY --from=node /usr/local/lib /usr/local/lib
# yarn command
COPY --from=node /opt /opt
```

[本家](https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4#copy-%E5%91%BD%E4%BB%A4-1)
> node のベースイメージから node と npm と yarn をコピーしています。
もし npm, yarn どちらか使用したくない場合は削除して使用してokです。

- View や React で画面を作った際に、動作するのが Nginx 側だから node を Nginx にコピーしてきてると思われる
    - [docker-compose 編](https://qiita.com/tkek321/items/9c0c5cec1dc349c67f5f#-laravel-%E3%81%AE%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88-1)
        - PHP は unix ソケットを使って、 PHP コンテナで動く、静的コンテンツは Nginx コンテナで動く

## ⑦ Nginx の設定ファイルをコピー

`COPY ./infra/docker/nginx/*.conf /etc/nginx/conf.d/`

- `./infra/docker/nginx/default.conf`をコピーしている

https://www.bnote.net/centos/nginx_conf01.html

https://blog1.mammb.com/entry/2020/09/01/000000#nginx-%E3%81%AE%E6%A7%8B%E6%88%90

- nginxの設定は、`/etc/nginx` ディレクトリの `nginx.conf` に記載される
- nginx.confに記述してある、 `include /etc/nginx/default.d/*.conf;` という記述で、`conf.d` ディレクトリ内の拡張子がconfであるファイルを読み込んでいる
- `/etc/nginx/conf.d/default.conf` にサーバーの設定を記載するのが一般的

- [設定ファイル](https://github.com/ucan-lab/docker-laravel/blob/main/infra/docker/nginx/default.conf)は別途確認

Nginx コンテナ内の `/etc/nginx/nginx.conf`は下記のような記載になっている。
`include /etc/nginx/conf.d/*.conf;` でコピーした設定ファイルが読み込まれるようになっている。

```conf:nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
```


## ⑧ 作業ディレクトリを指定

`WORKDIR /work/backend`

- [PHP 編](https://qiita.com/tkek321/items/5d7714d7170bbf379c11#-%E4%BD%9C%E6%A5%AD%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92%E6%8C%87%E5%AE%9A)と同じ
    - ここではディレクトリが生成されるだけのはず

# Nginx の設定ファイル

Laravel の公式ドキュメントを参考にしているらしい

https://readouble.com/laravel/8.x/ja/deployment.html#nginx

```conf:default.conf
access_log /dev/stdout main; # ① アクセスログの設定
error_log /dev/stderr warn; # ② エラーログの設定

server { # 以下、server コンテキスト
    listen 80; # ③ リクエストを受け付けるポート番号を指定
    root /work/backend/public; # ④ ドキュメントルートを設定

    # ⑤ レスポンスヘッダに値を追加
    add_header X-Frame-Options "SAMEORIGIN"; 
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php; # ⑥ インデックスとして使用されるファイルを指定

    charset utf-8; # ⑦ Content-Type を utf-8 に設定

    location / { # ⑧ アクセス URI にファイルがなければ index.php へ遷移させる
        try_files $uri $uri/ /index.php?$query_string;
    }

    # ⑨ アクセスログとエラーログが出ないように設定
    location = /favicon.ico { access_log off; log_not_found off; } 
    location = /robots.txt  { access_log off; log_not_found off; }
    # ⑩ 404 エラーの場合は index.php に遷移する
    error_page 404 /index.php;
    # ⑪ .php にアクセスした場合の設定
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
    # ⑫ well-known 以外のドットファイルへのアクセスを全て拒否
    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

## nginx の設定ファイルについ概要だけ確認

https://hack-le.com/nginx/#main%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E5%86%85

https://qiita.com/morrr/items/7c97f0d2e46f7a8ec967

https://www.wakuwakubank.com/posts/611-web-server-nginx/

- `http{ }` とか `server{ }` はディレクティブ（命令）
- ブロック{ }内の記述は、そのブロック内でのみ有効。その範囲をコンテキストという
- ディレクティブによって、どのコンテキストで使えるかが決まっている
    - serverディレクティブはhttpコンテキスト内でしか使えない
- どのブロックにも囲まれていないところはmainコンテキスト

## ホストの`./infra/docker/nginx/default.conf`が実行される場所

- Nginx の Dockerfile でホストの `./infra/docker/nginx/default.conf`　をコンテナ内の `/etc/nginx/conf.d/` ディレクトリ内にコピー

- コピーしたファイルはコンテナ内の Nginx の設定ファイル `/etc/nginx/nginx.conf` の http コンテキスト内から `include` されている

- つまり、`./infra/docker/nginx/default.conf`　には http コンテキスト内で実行されるディレクティブが書かれている

## ① アクセスログの設定

`access_log /dev/stdout main;`

http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log

- 指定したログフォーマットでアクセスログを書き出してくれる
- アクセスログのフォーマット 
    - `access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];`

- path が `/dev/stdout` になっているので、ここに access_log が出力されているはず

```bash
~ # ls -la /dev/
drwxr-xr-x    5 root     root           340 Dec 30 06:05 .
drwxr-xr-x    1 root     root          4096 Dec 30 06:05 ..
lrwxrwxrwx    1 root     root            11 Dec 30 06:05 core -> /proc/kcore
lrwxrwxrwx    1 root     root            13 Dec 30 06:05 fd -> /proc/self/fd
crw-rw-rw-    1 root     root        1,   7 Dec 30 06:05 full
drwxrwxrwt    2 root     root            40 Dec 30 06:05 mqueue
crw-rw-rw-    1 root     root        1,   3 Dec 30 06:05 null
lrwxrwxrwx    1 root     root             8 Dec 30 06:05 ptmx -> pts/ptmx
drwxr-xr-x    2 root     root             0 Dec 30 06:05 pts
crw-rw-rw-    1 root     root        1,   8 Dec 30 06:05 random
drwxrwxrwt    2 root     root            40 Dec 30 06:05 shm
lrwxrwxrwx    1 root     root            15 Dec 30 06:05 stderr -> /proc/self/fd/2
lrwxrwxrwx    1 root     root            15 Dec 30 06:05 stdin -> /proc/self/fd/0
lrwxrwxrwx    1 root     root            15 Dec 30 06:05 stdout -> /proc/self/fd/1
crw-rw-rw-    1 root     root        5,   0 Dec 30 06:05 tty
crw-rw-rw-    1 root     root        1,   9 Dec 30 06:05 urandom
crw-rw-rw-    1 root     root        1,   5 Dec 30 06:05 zero
```

- `/dev/stdout`はシンボリックリンクになっている

```bash
~ # ls -la /proc/self/fd
total 0
dr-x------    2 root     root             0 Dec 30 06:51 .
dr-xr-xr-x    9 root     root             0 Dec 30 06:51 ..
lrwx------    1 root     root            64 Dec 30 06:51 0 -> /dev/pts/0
lrwx------    1 root     root            64 Dec 30 06:51 1 -> /dev/pts/0
lrwx------    1 root     root            64 Dec 30 06:51 2 -> /dev/pts/0
ls: /proc/self/fd/3: cannot read link: No such file or directory
lr-x------    1 root     root            64 Dec 30 06:51 3
```

```bash
~ # ls -la /dev/pts
total 0
drwxr-xr-x    2 root     root             0 Dec 30 06:05 .
drwxr-xr-x    5 root     root           340 Dec 30 06:05 ..
crw--w----    1 root     tty       136,   0 Dec 30 06:52 0
crw-rw-rw-    1 root     root        5,   2 Dec 30 06:52 ptmx
```

- シンボリックリンクを辿っていくと [デバイスファイル](`/dev/stdout`)になっていた
- アクセスログはどうやって確認したらいいんだろ、わからん


- format は main になってる
	- おそらくコンテナ内の `nginx.conf` で設定されている `main` のフォーマットを指定している

```:nginx.conf
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
```


## ② エラーログの設定

`error_log /dev/stderr warn;`

http://nginx.org/en/docs/ngx_core_module.html#error_log

> error_log file [level];

> 2番目のパラメータはログのレベルを決定し、debug, info, notice, warn, error, crit, alert, emergのいずれかを指定します。上記のログレベルは、深刻度の高い順に記載されています。あるログレベルを設定すると、>指定された、より深刻なログレベルのすべてのメッセージがログに記録されるようになります。例えば、デフォルトレベルのerrorは、error、crit、alert、およびemergメッセージがログされるようにします。このパラメータ
が省略された場合、errorが使用されます。

- `/dev/stderr` にエラーログを出力
- `warn` レベル以上のログを出力

- access_log と同様にシンボリックリンクになって、たどるとデバイスファイルになっていた。確認方法がわからん

## ③ リクエストを受け付けるポート番号を指定

`listen 80;`

- [listen](https://nginx.org/en/docs/http/ngx_http_core_module.html#listen) ディレクティブでリクエストを受け付けるポートや IP アドレスを指定できる
- 今回は 80 番ポートでリクエストを受け付けるように設定している

[docker-compose.yml](https://qiita.com/tkek321/items/9c0c5cec1dc349c67f5f#-%E5%85%AC%E9%96%8B%E7%94%A8%E3%83%9D%E3%83%BC%E3%83%88%E3%82%92%E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0) で nginx 側の 80　番ポートとホストの 80 番ポートをマッピングしていたのはこのため

## ④ ドキュメントルートを設定

`root /work/backend/public;` 

- [root](https://nginx.org/en/docs/http/ngx_http_core_module.html#root)ディレクティブでドキュメントリュートを指定

- `/work/backend` は [docker-compose.yml](https://qiita.com/tkek321/items/9c0c5cec1dc349c67f5f#-laravel-%E3%81%AE%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88-1)で Laravel のソースコードをマウントするディレクトリ
- つまり、 Lravel の `public` ディレクトリをドキュメントルートに指定している

## ⑤ レスポンスヘッダに値を追加

- [add_header](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header) ディレクティブ

> レスポンスコードが 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), または 308 (1.13.0) であれば、指定したフィールドを応答ヘッダに追加します。パラメータ値には変数を含めることができる。

### `X-Frame-Options "SAMEORIGIN";`

- [X-Frame-Options](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Frame-Options#nginx_%E3%81%AE%E8%A8%AD%E5%AE%9A)

> X-Frame-Options は HTTP のレスポンスヘッダーで、ブラウザーがページを <frame>、<iframe>、<embed>、<object> の中に表示することを許可するかどうかを示すために使用します。サイトはコンテンツが他のサイトに埋め込まれないよう保証することで、ク
リックジャッキング攻撃を防ぐために使用することができます。

- SAMEORIGIN
        - 同じオリジンのフレーム内でのみ表示可能
- [nginx での設定](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Frame-Options#nginx_%E3%81%AE%E8%A8%AD%E5%AE%9A)


### `X-XSS-Protection "1; mode=block";`

- [X-XSS-Protection](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-XSS-Protection)

> HTTP の X-XSS-Protection レスポンスヘッダーは Internet Explorer, Chrome, Safari の機能で、反射型クロスサイトスクリプティング (XSS) 攻撃を検出したときに、ページの読み込みを停止するためのものです。

> 1; mode=block
XSS フィルタリングを有効化します。攻撃を検知すると、ページをサニタイジングするよりも、ページのレンダリングを停止します。

- [nginx での設定](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-XSS-Protection#:~:text=add_header%20%22X%2DXSS%2DProtection%22%20%221%3B%20mode%3Dblock%22%3B)

### `X-Content-Type-Options "nosniff";`

- [X-Content-Type-Options](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options)

> X-Content-Type-Options は HTTP のレスポンスヘッダーで、 Content-Type ヘッダーで示された MIME タイプを変更せずに従うべきであることを示すために、サーバーによって使用されるマーカーです。これにより、MIME タイプのスニッフィングを抑止するこ
とができます。言い替えれば、 MIME タイプを意図的に設定することができます。

> nosniff
リクエスト先のタイプが style でありその MIME タイプが text/css ではない場合、または、タイプが script で MIME タイプが JavaScript の MIME タイプではない場合にリクエストをブロックします。

## ⑥ インデックスとして使用されるファイルを指定

`index index.html index.htm index.php;`

- [incex](http://nginx.org/en/docs/http/ngx_http_index_module.html) ディレクティブ

> インデックスとして使用されるファイルを定義します。ファイル名には変数を含めることができる。ファイルは指定された順序でチェックされる。


- 今回は index.html, index.htm, index.php の優先順位で index ファイルが決まる
- index.html, index.htm ファイルがなければ、Laravel の index.php ファイルがインデックスファイルとして読み込まれる

- つまり、`http://localhost` でアクセスした時には `index.php` が呼ばれる


## ⑦ Content-Type を utf-8 に設定

`charset utf-8;`

[charset](http://nginx.org/en/docs/http/ngx_http_charset_module.html#charset)

> レスポンスヘッダーフィールド "Content-Type" に、指定された文字セットを追加します。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Type#:~:text=MIME%20%E3%82%BF%E3%82%A4%E3%83%97%E3%81%A7%E3%81%99%E3%80%82-,charset,-%E6%A8%99%E6%BA%96%E3%81%AE%E6%96%87%E5%AD%97


## ⑧ アクセス URI にファイルがなければ index.php へ遷移させる

### `location`
- リクエスト URI に応じた設定を行う
- 今回は、 `/` にアクセスがきた時の設定を行っている

https://heartbeats.jp/hbblog/2012/04/nginx05.html

- `/` で始まる全てのリクエスト URI に対して適応される


### `try_files $uri $uri/ /index.php?$query_string;`

- [try_files](http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files)

> 指定された順番でファイルの存在を確認し、最初に見つかったファイルをリクエスト処理に使用する。処理は、現在のコンテキストで実行される。ファイルへのパスは、fileパラメータからrootとaliasディレクティブに従って構築される。また、"$uri/" のよう>に名前の最後にスラッシュを指定することで、ディレクトリの存在を確認することができる。いずれのファイルも見つからなかった場合、最後のパラメータで指定された uri に内部リダイレクトされます。

https://qiita.com/k_hoso/items/33ccb5e02e73a244ed31

- アクセスしてきた URL にファイルがあるか
- アクセスしてきた URL にディレクトリがあるか
- いずれもなければ、`/index.php$query_string` へ遷移する

## ⑨ アクセスログとエラーログが出ないように設定

`location = /favicon.ico { access_log off; log_not_found off; }`
`location = /robots.txt  { access_log off; log_not_found off; }`

- `/favicon.ico` と `/robots.txt` にアクセスされた場合の設定

- [log_not_found](http://nginx.org/en/docs/http/ngx_http_core_module.html#log_not_found)
 
> ファイルが見つからない場合のエラーログをerror_logに記録するかどうかを設定します。

- [access_log](http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log)

    - アクセスログを off にしている

## ⑩ 404 エラーの場合は index.php に遷移する

[error_page](http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page)

> 指定されたエラーに対して表示されるURIを定義する。


## ⑪ .php にアクセスした場合の設定

```config
location ~ \.php$ {
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
```

https://qiita.com/k_hoso/items/33ccb5e02e73a244ed31#location--php-%E9%83%A8%E5%88%86%E3%81%AE%E8%A8%AD%E5%AE%9A

https://heartbeats.jp/hbblog/2012/04/nginx05.html

https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/#fastcgi-params

### `location ~ \.php$` 

- `~` 正規表現（大文字・小文字を区別する）
- `~ \.php$` 拡張子が .php のファイルに対して設定を行う

### `fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;` 

- [fastcgi_pass](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_pass)

> FastCGI サーバーのアドレスを設定します。
> UNIX-domain socket path:
> fastcgi_pass unix:/tmp/fastcgi.socket;

- unix ドメインソケットのパスを指定している
- [docker-compose.yml](https://qiita.com/tkek321/items/9c0c5cec1dc349c67f5f#-unix%E3%82%BD%E3%82%B1%E3%83%83%E3%83%88%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88-1) で unix ドメインソケットをマウントしているので、そこへのパスを指定する
- おそらくこれで、.php ファイルにアクセスした時は php コンテナと通信をして、　PHP コンテナの FastCGI で PHP を実行することができる


### `fastcgi_index index.php;`

- [fastcgi_index](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_index)

> スラッシュで終わる URI の後に付加されるファイル名を $fastcgi_script_name 変数の値に設定します。


### `fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;`

- [fastcgi_param](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_param)

> FastCGI サーバーに渡すべきパラメータを設定します。値にはテキスト、変数、およびそれらの組み合わせを含めることができます。

> PHPでは、SCRIPT_FILENAMEパラメータはスクリプト名を決定するために使用され、QUERY_STRINGパラメータはリクエストパラメータを渡すために使用されます。

- FastCGI サーバー（PHP コンテナ）に [SCRIPT_FILENAME](https://www.php.net/manual/ja/reserved.variables.server.php#:~:text=%E3%82%8C%E3%81%9F%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%80%82-,%27SCRIPT_FILENAME%27,-%E7%8F%BE%E5%9C%A8%E5%AE%9F%E8%A1%8C%E3%81%95) を渡している

    - SCRIPT_FILENAME パラメータは、 PHP FPM に渡す必要があるらしい


- [$realpath_root](https://nginx.org/en/docs/http/ngx_http_core_module.html#var_realpath_root)

> 現在のリクエストに対する root または alias ディレクティブの値に対応する絶対パス名。 すべてのシンボリックリンクは実際のパスに解決されます。

- とりあえず、ベタがきでも index.php のパスを指定すればいいらしい

なんで必要かまではわかっていない。

### `include fastcgi_params;`

- [fastcgi_params](https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/#fastcgi-params) を include している
    - PHP の `$_SERVER` 内に値が入る


## ⑫ well-known 以外のドットファイルへのアクセスを全て拒否

```
location ~ /\.(?!well-known).* {
        deny all;
    }
```

- `.well-known` ディレクトリは [Let's Encrypt](https://letsencrypt.org/ja/) で SSL の設定をする際に使ったりすることがあるらしい
    - https://qiita.com/HeRo/items/f9eb8d8a08d4d5b63ee9 
- それ以外のドットディレクトリへのアクセスは全て拒否している

- [deny](http://nginx.org/en/docs/http/ngx_http_access_module.html#deny)

> 指定されたネットワークまたはアドレスのアクセスを拒否する