docker-composeを利用して同一リポジトリでNuxt(web) + Laravel(API)な開発環境を準備する

## 概要
LaravelのBlade運用にツラさを感じてきてフロントを分離したくなったので調査して開発環境を準備した。
同一リポジトリにした理由はフロント側の開発をしている時に同一の方がAPIの検証をしやすいと思ったからです。
調査ついでに記事として残しておく。

## 環境
- Host:Mac
- Docker
    - nginx:1.19-alpine
    - node:13.8-alpine
    - php:7.4-fpm-alpine

## 完成イメージ
![spa_dev_template.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/fd0cb3cf-b5db-faca-356e-3765f4bc6a81.png)

## 完成品
https://github.com/nagi125/spa_dev_template
※ NuxtとLaravelのプロジェクトはREADME.mdを見て生成してください。

## ざっくり説明
「web」というディレクトリにNuxtのプロジェクト一式が、「api」というディレクトリにLaravelのプロジェクト一式が準備されます。
dockerのvolume機能を用いてNuxt側とLaravel側で、各種ファイルを共有しています。
そしてNuxt側はデフォルト位置を「/app」に、Laravel側もデフォルト位置を「/app」にしておけば完成です。


## 各コンテナについて
### Nginx
```Dockerfile
FROM nginx:1.19-alpine

ENV TZ Asia/Tokyo

COPY conf/default.conf /etc/nginx/conf.d/default.conf
```
#### Nginxのconfファイル
```conf
server {
    server_name         localhost;

    proxy_set_header    Host                 $host;
    proxy_set_header    X-Real-IP            $remote_addr;
    proxy_set_header    X-Forwarded-Host     $host;
    proxy_set_header    X-Forwarded-Server   $host;
    proxy_set_header    X-Forwarded-For      $proxy_add_x_forwarded_for;

    location / {
        proxy_pass    http://web:3000;
    }

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

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass   api:9000;
        fastcgi_index  index.php;

        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO $fastcgi_path_info;
    }
}
```
開発環境なので若干雑に作っている部分はあります。
/apiの場合はLaravelを見にいき、デフォルトはNuxtを見にいくようにRP設定してあります。
※FastCGIの場合は厳密にはRPと言わないかもしれませんが・・・。

### Nuxt.js
```Dockerfile
FROM node:13.8-alpine

RUN apk update && \
    apk add git && \
    apk add --no-cache curl && \
    curl -o- -L https://yarnpkg.com/install.sh | sh && \
    yarn add @vue/cli @vue/cli-service-global nuxt create-nuxt-app

ENV TZ Asia/Tokyo
ENV PATH $HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$PATH

WORKDIR /app

CMD ["/bin/ash"]
```
npmではなくyarn派なのでyarnを利用するように調整してあります。
作業領域を「/app」にしておきます。

### Laravel
```Dockerfile
FROM php:7.4-fpm-alpine

ENV TZ Asia/Tokyo
ENV COMPOSER_ALLOW_SUPERUSER 1

# install Lib
RUN apk update && \
    apk add --no-cache --virtual .php-builds oniguruma-dev git zip unzip

# add php-ext-module
RUN docker-php-ext-install mbstring && \
    docker-php-ext-enable mbstring

# install Composer
RUN curl -sS https://getcomposer.org/installer | php && \
    mv composer.phar /usr/local/bin/composer && \
    chmod +x /usr/local/bin/composer

WORKDIR /app
```
こちらのコンテナも作業領域を「/app」にしておきます。

### docker-compose
```yml

version: '3'
services:
  nginx:
    container_name: nginx
    build:
      context: ./docker/nginx
      dockerfile: Dockerfile
    ports:
      - 80:80
    tty: true
    restart: always
    depends_on:
      - web

  web:
    container_name: web
    build:
      context: ./docker/web
      dockerfile: Dockerfile
    environment:
      PORT: '3000'
      HOST: '0.0.0.0'
    expose:
      - 3000
    volumes:
      - ./web:/app
    stdin_open: true
    tty: true
    restart: always
    depends_on:
      - api

  api:
    container_name: api
    build:
      context: ./docker/api
      dockerfile: Dockerfile
    environment:
      LANG: 'ja_JP.UTF-8'
      TZ: 'Asia/Tokyo'
    volumes:
      - ./api:/app
    expose:
      - 9000
    tty: true
    restart: always
```
docker-composeではNuxtとLaravelのコンテナの「/app」をホストの「./web」と「./api」と共有します。
DBを追加したい場合はdocker-composeに書き足せばよいでしょう。

## 起動
上記まで準備できたら下記コマンドで開発環境が立ち上がるはずです。

```
$ docker-compose build
$ docker-compise up
```

## NuxtとLaravelプロジェクトの作成

### Nuxt
下記コマンドでNuxtプロジェクトの作成をします。
質問の答えについてはここでは省略します。
お好みの設定にしてください。

```
$ docker-compose exec web yarn create nuxt-app ./
```

下記コマンドで開発モードの立ち上げをします。

```
$ docker-compose exec web yarn dev
```

### Laravel
下記コマンドでLaravelプロジェクトの作成をします。
バージョンはお好みの物にしてください。

```
$ docker-compose exec api composer create-project --prefer-dist laravel/laravel ./ "6.*"
```

## 完成
NuxtとLaravelのプロジェクトの生成が完了すれば開発環境として利用できるようになります。
Nuxt側には「localhost」で、Laravel側には「localhost/api」でアクセスできます。
※Laravel側のroute設定を忘れずに。

## 本番運用は？
開発用のDockerfileなので本番でECSとかを利用する場合はこちらはDockerfile.devとして、本番用のDockerfileを各ディレクトリに準備してください。

## 最後に
調査内容のメモとなりますが、何かのお役に立てれば幸いです。