Laravel × Nuxt.jsのDocker環境を作る

# 導入
こんにちはhagurereです。
今回はLaravel × Nuxt.jsの環境をdocker-composeで作成したのでその工程を残します。

# Version
## backend
php  8.1-fpm
laravel. 9.11

## frontend
node  16.13.1-alpine
nuxt 2.15.7

# ファイル構成
![スクリーンショット 2022-06-17 0.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1178067/e019f901-a644-368d-e242-0c453e2aa6b0.png)


# Nuxtコンテナの作成
とりあえずrootディレクトリ作成(自分の場合はホームディレクトリの下のprivateディレクトリの下)
```
cd ~/private && mkdir laravel-nuxt && cd laravel-nuxt
```

nuxt app 作成(command not foundと出る場合はnpmのセットアップから)
```
npm init nuxt-app frontend
```

Dockerfile, docker-compose.yml作成
```
touch frontend/Dockerfile
touch docker-compose.yml
```

Dockerfileに以下を書き込む
```
FROM node:16.13.1-alpine

WORKDIR /usr/src/app

ENV LANG=C.UTF-8
ENV TZ =Asia/Tokyo
```

docker-compose.ymlに以下を追記
```
version: "3.7"
services:
  frontend:
    build: ./frontend
    environment:
      - NODE_ENV=development
      - HOST=0.0.0.0
      - CHOKIDAR_USEPOLLING=true
    volumes:
      - ./frontend:/usr/src/app
    command: sh -c 'npm install && npm run dev'
    ports:
      - '3000:3000'
    tty: true
```

一旦frontendコンテナだけで立ち上げてみます
```
docker-compose up -d frontend
```
以下にアクセスしてみる(立ち上がるまで何十秒かかかります)
http://localhost:3000

# Laravelコンテナの作成
laravelのプロジェクト作成(command not foundが出る人はcomposerのセットアップから)
```
composer create-project laravel/laravel backend
```

Dockerfile作成 & 記入
```
touch backend/Dockerfile
```
```
FROM php:8.1-fpm

COPY --from=composer:2.3.5 /usr/bin/composer /usr/bin/composer
COPY php.ini /etc/php/8.1/cli/conf.d/99-etc.ini

ADD docker-entrypoint.sh ./
RUN chmod +x ./docker-entrypoint.sh
CMD ["./docker-entrypoint.sh"]

WORKDIR /var/www/laravel
```

php.ini作成 &　記入
```
touch backend/php.ini
```
```
# php.ini
[PHP]
post_max_size = 100M
upload_max_filesize = 100M
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

extension=redis.so
```

docker-entrypoint.sh作成 & 記入
```
touch backend/docker-entrypoint.sh
```
```
# docker-entrypoint.sh
# Install Laravel packages
composer install

if [ ! -e ./.env ]; then
  cp .env.example .env
fi

php artisan serve --host=0.0.0.0
```

docker-compose.ymlに以下を追記
```
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ports:
      - '3000:3000'
    tty: true
# ここから下を追記
  backend:
    build: ./backend
    tty: true
    volumes:
        - ./backend:/var/www/laravel
    ports:
      - '8000:8000'
    env_file:
      - ./backend/.env
```

backend/.envを作成しておく
```
cp backend/.env.example backend/.env
```

backendコンテナを立ち上げてみる
```
docker-compose up -d backend
```
以下にアクセスしてみる

http://localhost:8000

# Mysqlコンテナ作成 & Laravelとの接続
env作成 & 記入
```
touch .env
```
環境ごとに適当な値を入れてください
```
DB_DATABASE=database
DB_USERNAME=user
DB_PASSWORD=password
DB_ROOT_PASSWORD=root
```

laravelのenv書き換え
```
# 11行目=16行目の以下の部分を上の.envと同じ値にする
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=database
DB_USERNAME=user
DB_PASSWORD=password
```

docker-compose.ymlに追記
```
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ports:
      - '8000:8000'
    env_file:
      - ./.env
# ここから下を追記する
  mysql:
    image: mysql/mysql-server:5.7
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    ports:
      - '3306:3306'
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: '${DB_ROOT_PASSWORD}'
      MYSQL_DATABASE: '${DB_DATABASE}'
      MYSQL_USER: '${DB_USERNAME}'
      MYSQL_PASSWORD: '${DB_PASSWORD}'
    volumes:
      - /var/lib/mysql
    env_file:
      - ./.env
```
mysqlコンテナを立ち上げてみる
```
docker-compose up -d mysql
```

migrationを叩いてみる
```
docker-compose exec backend php artisan migrate
```

migrationが通ればうまくいってます

# nginxコンテナの作成
必要なファイル, ディレクトリ作成
```
mkdir nginx
touch nginx/Dockerfile
mkdir nginx/conf
touch nginx/conf/default.conf
```

Dockerfileに以下を記入
```
# nginx/Dockerfile
FROM nginx:1.19
RUN apt-get update && \
    apt-get install -y apt-utils \
    locales && \
    sed -i -e 's/# ja_JP.UTF-8/ja_JP.UTF-8/g' /etc/locale.gen && \
    locale-gen ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LC_TIME C
ENV TZ Asia/Tokyo
RUN echo "${TZ}" > /etc/timezone \
    && dpkg-reconfigure -f noninteractive tzdata
COPY conf/default.conf /etc/nginx/conf.d/default.conf
```

default.confに以下を記入
```
server {
  listen 80;
  root /app/public;

  location / {
    proxy_pass    http://frontend:3000;
  }
  location /api {
    proxy_pass http://backend:8000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    add_header X-Server-Hostname $hostname;
    add_header X-Server-Address $server_addr;
  }

  client_max_body_size 100m;
  keepalive_timeout 5;
}
```

docker-compose.ymlに以下を追記
```
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    command: sh -c 'npm install && npm run dev'
    ports:
      - '3000:3000'
    tty: true
# ここから下追記
  nginx:
    build:
      context: ./nginx/
      dockerfile: Dockerfile
    ports:
      - 80:80
    tty: true
    restart: always
    depends_on:
      - frontend
      - backend
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
```

立ち上げてみる
```
docker-compose up -d nginx
```
これにアクセスしてnuxtが表示されることを確認する

http://localhost

これにアクセスしてlaravelが表示されることを確認する(404が出るのはweb.phpに/apiのrouteが定義されてないからです)

http://localhost/api


# 最後に
この作り方だとホストにcomposerやnpmを持っておかないといけないのが難点ですがスマートに作れていいなと思います。
node×reactとかlaravel×reactとかも同じ感じで作れます。
エラーが出てうまくいかないよって方はコメントいただけると気づいた時に返します。

# source
https://github.com/YuuseiMatsunaga/laravel-nuxt