ubuntuでLaravel8.xをDockerを使って構築

<h1>初めに</h1>
Dockerを使ってLaravelを構築しようと思ったので、構築しました。

[Dockerについて](https://knowledge.sakura.ad.jp/13265/)
[DockerComposeについて](https://docs.docker.jp/compose/overview.html#:~:text=Compose%20%E3%81%A8%E3%81%AF%E3%80%81%E8%A4%87%E6%95%B0%E3%81%AE,%E7%94%9F%E6%88%90%E3%80%81%E8%B5%B7%E5%8B%95%E3%82%92%E8%A1%8C%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)
<h1>環境  </h1>
今回構築に使用した環境

```zsh
% lsb_release -a                                                                                                                                                                                                                
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.2 LTS
Release:	20.04
Codename:	focal

% docker -v                                                                                                                                                                                                                     
Docker version 20.10.11, build dea9396

% docker-compose -v                                                                                                                                                                                                             
Docker Compose version v2.2.1
```
<h1>構成</h1>
以下の構成を想定して作成します。

```zsh
% tree                                                                                                                                                                                                                        
.
├── docker
│   ├── nginx
│   │   └── default.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
├── docker-compose.yml
└── web

```

<h2>1 Docker Compose</h2>
Composeは主に、複数のコンテナを定義するためのファイルである。
Composeにおいてはymlファイルを使ってアプリケーションサービスの設定を行います。

```yml
version: '3'

volumes:
  vendor-store:
  node_modules-store:

services:
  php:
    container_name: php
    build: ./docker/php
    volumes:
    - ./web:/var/www
    - vendor-store:/var/www/laravel/vendor
    - node_modules-store:/var/www/laravel/node_modules
    environment:
      TZ: Asia/Tokyo

  nginx:
    image: nginx
    container_name: nginx
    ports:
    - 8085:80
    volumes:
    - ./web:/var/www
    - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
    - php

  db:
    image: mysql:8.0
    container_name: db
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: database
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
    - ./docker/db/data:/var/lib/mysql
    - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
    - ./docker/db/sql:/docker-entrypoint-initdb.d
    ports:
    - 4306:3306

```
<h5>Serviceとは</h5>
アプリケーションを動かすための要素のこと。

<h5>imageとは </h5>
Nginxとdb(mysql)についてはDockerHubに上がっている既存のDockerImagesを使っている。

<h5>buildとは</h5>
Dockerfile のあるディレクトリのパスを指定する。この値が相対パスで指定された場合は、yml ファイル自身がある場所からの相対パスになる。

<h5>volumesとは</h5>
パスを指定して、パスをボリュームとしてマウントする。
<h2>2 Dockerfile </h2>

```Dockerfile
FROM php:8.0-fpm

COPY php.ini /usr/local/etc/php/

RUN apt update
RUN apt install -y wget git unzip libpq-dev

# Install Node.js 14
RUN apt install -y npm \
  && npm install n -g \
  && n 14

# Install PHP Extensions
RUN apt install -y zlib1g-dev mariadb-client libzip-dev libonig-dev \
  && docker-php-ext-install zip pdo_mysql

# Install Composer
RUN curl -sS https://getcomposer.org/installer | php \
  && mv composer.phar /usr/local/bin/composer \
  && composer self-update
WORKDIR /var/www

# php-fpmはデフォルトのユーザwww-dataで動く。https://stackoverflow.com/questions/48619445/permission-denied-error-using-laravel-docker
# 変更する場合は /usr/local/etc/php-fpm.d/www.conf でユーザー名を変える。
RUN chown -R www-data:www-data /var/www

RUN composer global require "laravel/installer"
```
<h5>FROM </h5>
新しい 構築ステージbuild stage を初期化し、以降の命令で使う ベース・イメージ を指定します
<h5>RUN には２つの形式がある</h5>

```
RUN <コマンド> （ シェル形式shell form 。コマンドはシェル内で実行される。デフォルトは Linux が /bin/sh -c で、 Windows は cmd /S /C ）
RUN ["実行ファイル", "パラメータ1", "パラメータ2"] （ 実行形式exec form ）
```
RUNコマンドは、FROMで記載したベースイメージに対して追加で行っていく処理を表す。
<h5>COPY</h5>
追加したいファイル、ディレクトリを <コピー元> で指定すると、これらをイメージのファイルシステム上のパス <コピー先> に追加される。

<h5>WORKDIR</h5>
Dockerfile 内で以降に続く RUN 、 CMD 、 ENTRYPOINT 、 COPY 、 ADD 命令の処理時に（コマンドを実行する場所として）使う 作業ディレクトリworking directory を指定する。

<h2>4 php.ini</h2>
(php.ini) は PHP の起動時に読み込まれる。

```ini
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
```

<h2>5 Nginx</h2>
```conf

server {
  listen 80;
  root /var/www/laravel/public;

  add_header X-Frame-Options "SAMEORIGIN";
  add_header X-XSS-Protection "1; mode=block";
  add_header X-Content-Type-Options "nosniff";

  index index.php;
  charset utf-8;

  location / {
    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; }

  error_page 404 /index.php;

  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    include fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
  }
  location ~ /\.(?!well-known).* {
      deny all;
  }
 }
```
LaravelをNginxで動作させる設定。 
ApacheではLaravel同梱の.htaccessが設定してくれるのだがNginxでは.htaccessに当たるものがないためNginxのconfを修正する必要となる。