docker-composeでLaravelローカル環境を構築（Laradockは使わない）

初学者向けのものです。初学者がわからなくなるコマンド叩いていたらローカル側なのかコンテナ側なのかわからなくなってグチャグチャにならないように、ローカル側でのみコマンド実行すれば良いように構築しています。

# 前提
+ 本番環境向けの最適化された設定ではないので、Dockerイメージをそのまま本番利用はしないように注意ください
+ Macユーザ向けです
+ 以下、インストール済みであること
 - [docker + docker-compose](https://docs.docker.com/docker-for-mac/install/)
 - git
+ nginx,php-fpm,composer,mysqlの環境を作ります

# インストール
## ホームディレクトリに移動して、プロジェクトフォルダを作成
<font color=red>projectsフォルダが無いことを確認してください</font>
<font color=red>`HogeApp`は自由に変更して大丈夫です</font>

``` cmd
$ cd ~
$ mkdir -p projects/HogeApp/{docker,src}
```
こんなフォルダができる

```
projects
└── HogeApp
    ├── docker
    └── src
```
## docker用ディレクトリを作成

``` cmd
$ cd ~/projects/HogeApp/docker
$ mkdir -p {nginx/conf.d,php-fpm,mysql-data}
```
## Nginxの設定
### Dockerfile(Nginx)
``` cmd
$ vim nginx/Dockerfile
```
以下を保存
<details><summary>nginx/Dockerfile</summary><div>

```  Dockerfile:nginx/Dockerfile
FROM nginx:1.15.9-alpine

EXPOSE 80
RUN apk update && apk upgrade \
    && rm -r /var/cache/apk/*

COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./conf.d/default.conf /etc/nginx/conf.d/default.conf
COPY ./conf.d/php-upstream.conf /etc/nginx/conf.d/php-upstream.conf
```
</div></details>
### nginx.conf
``` cmd
$ vim nginx/nginx.conf
```
以下を保存
<details><summary>nginx/nginx.conf</summary><div>

``` conf:nginx/nginx.conf
user  nginx;
worker_processes  1;

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

events {
    worker_connections  1024;
}

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

    log_format json_combined escape=json '{ "time_local": "$time_local", '
     '"remote_addr": "$remote_addr", '
     '"remote_user": "$remote_user", '
     '"request": "$request", '
     '"status": "$status", '
     '"body_bytes_sent": "$body_bytes_sent", '
     '"request_time": "$request_time", '
     '"http_referrer": "$http_referer", '
     '"http_user_agent": "$http_user_agent" }';
    
    access_log  /var/log/nginx/access.log json_combined;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    server_tokens off;

    server_names_hash_max_size 512;

    include /etc/nginx/conf.d/*.conf;
}
```
</div></details>
### default.conf
``` cmd
$ vim nginx/conf.d/default.conf
```
以下を保存
<details><summary>nginx/conf.d/default.conf</summary><div>

``` conf:nginx/conf.d/default.conf
server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /var/www/public;
    index index.php index.html index.htm;
    charset utf-8;

    location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|svg|mp3)$ {
        try_files $uri =404;
    }

    location / {
         try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_pass php-upstream;
        fastcgi_index index.php;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HOME /var/www;
        include fastcgi_params;
    }
}
```
</div></details>
### php-upstream.conf
``` cmd
$ vim nginx/conf.d/php-upstream.conf
```
以下を保存
<details><summary>nginx/conf.d/php-upstream.conf</summary><div>

``` conf:nginx/conf.d/php-upstream.conf
upstream php-upstream {
  server php-fpm:9000;
}
```
</div></details>
## PHP-FPMの設定
### Dockerfile(php-fpm)
``` cmd
$ vim php-fpm/Dockerfile
```
以下を保存
<details><summary>php-fpm/Dockerfile</summary><div>

``` Dockerfile:php-fpm/Dockerfile
FROM php:7.3-fpm-alpine

# Install PHP extensions
RUN apk update && apk upgrade --update && apk --no-cache add \
    git \
    vim less \
    icu-dev \
    autoconf \
    make \
    g++ \
    gcc \
    mysql-client \
    && rm -r /var/cache/apk/*

RUN docker-php-ext-install -j$(nproc) \
    iconv \
    intl \
    mbstring \
    pdo_mysql

COPY  ./php.ini /usr/local/etc/php/conf.d/my-php.ini
COPY  ./php-fpm.conf /usr/local/etc/php-fpm.d/my-php-fpm.conf
```
</div></details>
### php.ini
``` cmd
$ vim php-fpm/php.ini
```
以下を保存
<details><summary>php-fpm/php.ini</summary><div>

``` Dockerfile:php-fpm/php.ini
; timezone
date.timezone = Asia/Tokyo

; error reporing
log_errors = On
error_log = /dev/stderr
display_errors = Off

; mbstring
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
```
</div></details>
### php-fpm.conf
``` cmd
$ vim php-fpm/php-fpm.conf
```
以下を保存
<details><summary>php-fpm/php-fpm.conf</summary><div>

``` Dockerfile:php-fpm/php-fpm.conf
[www]
pm.status_path = /phpfpm_status
```
</div></details>

## docker-composeの設定
``` cmd
$ cd ~/projects/HogeApp
$ vim docker-compose.yml
```
以下を保存
<details><summary>docker-compose.yml</summary><div>

``` yaml:docker-compose.yml
version: "3"

services:
  nginx:
    build: ./docker/nginx
    container_name: "nginx"
    ports:
      - "8080:80"
    restart: always
    volumes:
      - ./src:/var/www
    depends_on:
      - php-fpm
  php-fpm:
    build: ./docker/php-fpm
    container_name: "php-fpm"
    restart: always
    volumes:
      - ./src:/var/www
    working_dir: /var/www
    links:
      - mysql
    depends_on:
      - mysql
  composer:
    image: composer:1.8
    container_name: "composer"
    volumes:
      - ./src:/var/www
    working_dir: /var/www
  mysql:
    image: mysql:5.7
    container_name: "mysql"
    ports:
      - 33306:3306
    restart: always
    volumes:
      - ./docker/mysql-data:/var/lib/mysql
    environment:
      MYSQL_DATABASE: hoge-db
      MYSQL_USER: hoge-user
      MYSQL_PASSWORD: hoge-password
      MYSQL_ROOT_PASSWORD: root
      TZ: "Asia/Tokyo"
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```
<font color=red>以下の環境変数部分はアプリに合わせて変更してください</font>
>environment:
>  MYSQL_DATABASE: hoge-db
>  MYSQL_USER: hoge-user
>  MYSQL_PASSWORD: hoge-password
>  MYSQL_ROOT_PASSWORD: root
</div></details>

## ここまでの作成ファイルたちとフォルダ構成
``` cmd
projects
└── HogeApp
    ├── docker
    │   ├── mysql-data
    │   ├── nginx
    │   │   ├── Dockerfile
    │   │   ├── conf.d
    │   │   │   ├── default.conf
    │   │   │   └── php-upstream.conf
    │   │   └── nginx.conf
    │   └── php-fpm
    │       ├── Dockerfile
    │       ├── php-fpm.conf
    │       └── php.ini
    ├── docker-compose.yml
    └── src
```

## コンテナ起動
``` cmd
$ cd ~/projects/HogeApp
$ docker-compose up -d
```
ズラズラっとコマンドが流れて最後にこれが出ればOK
>Creating composer ... done
Creating mysql    ... done
Creating php-fpm  ... done
Creating nginx    ... done

念の為、起動確認

``` cmd
$ docker-compose ps

  Name                Command               State                  Ports
---------------------------------------------------------------------------------------
composer   /bin/sh /docker-entrypoint ...   Exit 0
mysql      docker-entrypoint.sh mysql ...   Up       0.0.0.0:33306->3306/tcp, 33060/tcp
nginx      nginx -g daemon off;             Up       0.0.0.0:8080->80/tcp
php-fpm    docker-php-entrypoint php-fpm    Up       9000/tcp
```
この時点では、[http://localhost:8080/](http://localhost:8080/)にアクセスしても
`File not found.`となっているはず。

## Laravelインストール
``` cmd
$ cd ~/projects/HogeApp
$ docker-compose run composer global require laravel/installer
$ docker-compose run composer create-project --prefer-dist laravel/laravel .
```
まぁまぁ時間かかるので、待ちます・・・
おわったら、srcフォルダにlaravelのファイル郡ができています。
### もし以下エラーが出たら、別のネットワーク（テザリングとか、会社とかスタバとか）で試してください。
<font color=red>※この記事を見てもらう想定の「某学校」の人たちは絶対エラーなります。</font>

```
[Composer\Downloader\TransportException]                                                                                 
  The "https://repo.packagist.org/packages.json" file could not be downloaded: failed to open stream: Network unreachable
```

## ディレクトリのパーミッション変更
```
$ chmod -R a+w src/storage/*
```

### 確認
[http://localhost:8080/](http://localhost:8080/)にアクセスすると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/20763/f3ed83dc-be91-b27c-7a08-153c21e56e1f.png)

## Laravelの設定
`.env`ファイルをいじって、設定していきます。

```
$ vim src/.env
```
<details><summary>src/.env</summary><div>

``` diff
- APP_NAME=Laravel
+ APP_NAME=ご自身のアプリの名称に変更

- APP_URL=http://localhost
+ APP_URL=http://localhost:8080

- DB_HOST=127.0.0.1
+ DB_HOST=mysql

- DB_DATABASE=homestead
- DB_USERNAME=homestead
- DB_PASSWORD=secret
+ DB_DATABASE=hoge-db               # ← docker-compose.ymlのenvironmentで設定したやつ
+ DB_USERNAME=hoge-user
+ DB_PASSWORD=hoge-password
```
</div></details>

## 最終的なフォルダ構成
``` shell
projects
└── HogeApp
    ├── docker
    │   ├── mysql-data
    │   ├── nginx
    │   │   ├── Dockerfile
    │   │   ├── conf.d
    │   │   │   ├── default.conf
    │   │   │   └── php-upstream.conf
    │   │   └── nginx.conf
    │   └── php-fpm
    │       ├── Dockerfile
    │       ├── php-fpm.conf
    │       └── php.ini
    ├── docker-compose.yml
    └── src
        ├── app
        ├── ~省略~
        └── vendor
```

あとはローカルのsrcフォルダ配下のLaravelを触っていけば基本的にOKです！
# 開発時の注意点
### コマンドは`docker-compose.yml`ファイルがあるフォルダで実行してください
### composerの実行
`docker-compose run`をコマンドの頭につけてください

``` cmd:例
$ docker-compose run composer dump-autoload
```
### artisanの実行
`docker-compose exec php-fpm`をコマンドの頭につけてください

``` cmd:例
$ docker-compose exec php-fpm php artisan route:list
```
### コンテナの起動/終了
``` cmd:起動
$ docker-compose up -d
```
``` cmd:終了
$ docker-compose down
```
### コンテナにログインしたいとき
```
$ docker-compose exec php-fpm /bin/ash
```
# 最後に
ご自身のアプリに合わせて必要応じてRedisやphpmyadminなどをdockerイメージで追加して、拡張していってください。