Docker(Ubuntu20.04)+Laravel+nginxで環境構築

あまりDockerが得意ではない自分の自己学習の備忘録として作成。

## 概要

host環境にWebサーバーを構築する場合に、ローカル環境にhostと同様のOSで構築したくなったりしませんか？？
今回はhost環境として、ubutu（20.04）、リバースプロキシをnginx、アプリフレームワークをlaravelで行ってみましたので、
その内容を共有いたします。

### システム構成

- hostサイド
  - PC
        - Mac book pro
            - OSはCatalinaを使用
  - Docker
        - v3.03
- docker
    - 構成
        - 1コンテナ内にNginxとLaravelを構成
            - イメージはubuntu(20.04)
        - コンテナ作成はcomposerを使って実施
            - ソースはvolume設定でhostから読み出しが行えるように設定

#### フォルダ構成

```
Laravel ## PJのルートディレクトリ
├── docker
│   ├── Dockerfile
│   ├── docker-compose.yml
│   ├── entrypoint.sh
│   └── etc
│       ├── nginx
│       │   └── conf.d
│       │       └── laravel_sample.conf
│       └── php
│           └── 7.4
│               └── fpm
│                   └── pool.d
│                       └── www.conf
└── phpsample ## laravelプロジェクトフォルダ(composerでサンプルプロジェクトをダウンロード)
```


#### PC(host)環境構築

1. dockerとcomposerをhomebrewよりinstall

```
$ brew install docker
$ brew install composer
```

### Docker構築
#### Laravel構築

- とりあえず今回はサンプル用としてのcomposerでLaravelのサンプルプロジェクトを作成する
- Laravelのバージョンは最新の8.0とする

```
$ composer create-project --prefer-dist laravel/laravel:^8.0 phpsample
```
#### Dockerファイル作成

- 以下の内容を設定する
    - laravel起動に必要なphpのパッケージのインストールを実施
    - リバースプロキシとしてnginxのインストールを実施
    - コンテナ作成時にカスタマイズしたnginxやphp-fpmのconfの内容が読み出しされるようにするため、カスタマイズしたconfファイルをCOPY
    - php-fpmのsocketファイルがbuild時に生成されなかったのでentrypointで起動するようにする
        - 上記に付随する形でnginxのサービス起動もentrypointで実施するようにする

```

From ubuntu:20.04
LABEL Name=web_app_test

ENV TZ Asia/Tokyo

RUN apt-get update && apt-get install -y \
  tzdata  \
  php-mbstring  \ 
  php-xml  \ 
  php-fpm   \
  php-zip  \
  php-common  \ 
  php-fpm   \
  php-cli   \
  unzip   \ 
  curl   \ 
  nginx   \
  && mkdir /home/ubuntu   \
  && rm -f /etc/nginx/sites-enabled/default

COPY /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/www.conf
COPY ./entrypoint.sh /entrypoint.sh
COPY /etc/nginx/conf.d/laravel_sample.conf /etc/nginx/conf.d/laravel_sample.conf

ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "bash" ]
```

##### entrypoint.sh作成

- 以下の内容を設定する
    - 最後におまじないとして`exec "$@"`の実施が必須（筆者はこれを忘れており何度も失敗していた状況）
        - これが必要な理由としてはdockerの公式ドキュメントに記載がある通り、unixシグナルが受信できるようにするためのとのこと。詳しくは、[Dokcerの公式のリファレンス](http://docs.docker.jp/v17.06/engine/reference/builder.html)を参照

```
#!/bin/sh
  
service nginx start
service php7.4-fpm start
exec "$@"
```

##### php-fpmのconf(/etc/php/7.4/fpm/pool.d/www.conf)作成

- 以下の内容を設定する
    - nginxのuserとgroupが`www-data`となるため、listen.ownerやlisten.groupは合わせて修正
    
```
[www]
user = www-data
group = www-data
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
```

##### nginxのconf(laravel_sample.conf)作成

- 以下の内容を設定する
    - laravelを`/phpsample`に配置するため、rootを`/phpsample/public`として設定
    - locationのphpを設定する
        - `fastcgi_pass`は先のphp-fpmで設定したsocketのパスとする

```
server {
	listen 80 default_server;
	listen [::]:80 default_server;

	root /phpsample/public;

	# Add index.php to the list if you are using PHP
	index index.html index.php index.htm index.nginx-debian.html;

	server_name _;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		try_files $uri $uri/ =404;
	}

	# pass PHP scripts to FastCGI server
	#
	location ~ \.php$ {
		include snippets/fastcgi-php.conf;
	
		# With php-fpm (or other unix sockets):
		fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
		# With php-cgi (or other tcp sockets):
	#	fastcgi_pass 127.0.0.1:9000;
	}

	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	#location ~ /\.ht {
	#	deny all;
	#}
}
```

#### Docker composer作成

- 以下の通り設定する
    - ソースコードはvolumesを使ってhostから読み出しできるようにする
    - 念のためbashのプロセスは`pid 1`とならないようにするために`init:true`とする

```
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: "laravel-app"
    volumes:
      - ../phpsample:/phpsample/
    ports:
      - "80:80"
    tty: true
    init: true
```

### build＆コンテナ作成

以下の通りコマンドを入力し、イメージのbuild並びにコンテナを作成する

```
$ docker-compose build
$ docker-compose up -d
```

ブラウザで`localhost/`と入力するサンプルのLaravelのアプリが表示されることを確認

![スクリーンショット 2020-12-31 12.53.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516324/16a6f67f-d502-d40f-5ad6-f0d15ce85f96.png)