DockerでLaravel 7+ Nuxt.jsの動作環境をMacから構築する(Nginx+php7.3+MySQL5.7)
目次
やりたい事
・Laravel(API) + Nuxt.js(SSR・フロント)でのWEBアプリ開発の勉強の作業環境をすぐに欲しい
・Dockerを使う理由としては次のステップとしてAWSにデプロイしたい為
各バージョンなど
CentOS 7
Laravel 7
Nodejs
Nuxt.js
MySQL 5.7
Apache
PHP 7.3
※適切なバージョンを選定しないとLaravel7が動作しない場合があるので注意
MacにDockerをインストール
#MacにDocker Desktopをインストール
Mac版をGetDockerボタンを押下してインストール
インストールできればアプリを開きデスクトップ画面上部のくじらアイコンをクリックして、
起動状態になっていることを確認する。(Desktop running)
DockerComposeのインストール
#DockerComposeの説明
docker-compose.yml がある階層まで移動してコマンドを実行する
起動・停止・再起動のコマンド
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 起動 sudo docker-compose up ## バックグラウンド実行なら「-d」を付けてup sudo docker-compose up -d ## サービスを指定して起動するなら sudo docker-compose up nginx # 停止 sudo docker-compose stop ## 停止かつコンテナを削除 sudo docker-compose down ## イメージも合わせて削除 sudo docker-compose down --rmi all # 再起動 sudo docker-compose restart |
起動中のコンテナに入りたい時
1 2 3 4 5 6 |
# docker起動 docker-compose up -d # phpコンテナに入ります docker-compose exec php bash |
Laravel 7+ Nuxtjs環境を構築(ここから本題)
#前提
管理画面のフロント側としてNuxt.jsを利用する
バックエンドをAPIとしてLaravelで作成する
#参考記事
https://qiita.com/A-Kira/items/be0602fe28b445e865db
基本的には上記サイトの通り進めていく
#やりたい事
Mac内に共有フォルダ(作業フォルダ)
laravel-sanctumで『SPAの認証機能』を実装
Nuxtのログイン画面からaxiosでログイン
#フォルダ構成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
doclaraNuxt ├─docker │ ├── mysql │ │ └── my.cnf │ ├── ui (nodejsコンテナ//Nuxtjs用) │ │ └── Dockerfile │ ├── web │ │ ├── Dockerfile │ │ └── default.conf │ └── api (phpコンテナ//laravel用) │ ├── Dockerfile │ ├── start.sh │ └── php.ini ├─api │ └── laravelプロジェクト(app / .env など ) ├─ui │ └── nuxtjsプロジェクト(pages / store など) ├─db-store (自動作成される) └─ docker-compose.yml |
#ディレクトリの作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
mkdir doclaraNuxt //各コンテナ情報を作成 cd doclaraNuxt mkdir docker mkdir api mkdir ui //dockerディレクトリに移動して作成 cd docker mkdir api mkdir mysql mkdir ui mkdir web //apiディレクトリに移動してlaravelプロジェクト作成 後ほど記事で説明 //uiディレクトリに移動してNuxtjsプロジェクト作成 後ほど記事で説明 vi docker-compose.yml |
#docker-compose.yml の作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
version: '3' services: web: build: ./docker/web/ #Dockerfileが存在するディレクトリの相対パス ports: #ポートを公開する(ホスト:コンテナ) # - '8000:80' #8000でアクセスされたら、80を使用する - '8080:8080' #8080でアクセスされたら、8080を使用する volumes: #コンテナと共有したいパスを指定 - ./index.html:/var/www/html/index.html #確認用のhtmlをコンテナ側の/var/wwww/html配下にマウントする - ./docker/web/httpd.conf:/usr/local/apache2/conf/httpd.conf #httpd.confを上書きする - ./logs:/usr/local/apache2/logs/httpd/ # コンテナに入らず、apacheのlogを見るためマウントしとく depends_on: # Service同士の依存関係を指定 - ui #`docker-compose run`した際にapacheより前にuiコンテナが実行される links: #他のコンテナに接続する(コンテナのhostsに追加される) - ui ui: build: context: ./ dockerfile: ./docker/ui/Dockerfile volumes: - ./ui:/app depends_on: - api links: - api api: build: context: ./ dockerfile: ./docker/api/Dockerfile ports: - '8000:8000' volumes: - ./api:/var/www/html depends_on: - db links: - db db: image: mysql:8 volumes: - ./db-store:/var/lib/mysql - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf - ./logs:/var/log/mysql ports: - "4306:3306" environment: - MYSQL_DATABASE=dev - MYSQL_USER=dev - MYSQL_PASSWORD=password - MYSQL_ROOT_PASSWORD=password |
[説明]
version: ’3’ // Dockerのバージョンの事
services : //コンテナを登録 (今回の場合: php / nginx / db )
└ php : //imageを指定していない
└ build: ./laranuxtproj/docker/php 配下の Dockerfile を参照して構築
└ volumes: ローカルの ./src と /var/www をマウント
└ nginx :
└ image: nginxの公式イメージを使用
└ ports: host 80番:guest 80番 ポートで接続 // laravel 用 (http)
└ ports: host 443番:guest 443番 ポートで接続 // laravel 用 (https) SSL化
└ ports: host 3000番:guest 3000番 ポートで接続 // Nuxt.js 用
└ volumes: ローカルの ./laranuxtproj/docker/nginx/default.conf と
/etc/nginx/conf.d/default.conf をマウント
└ db :
└ imageにmysql:5.7を指定
└ restart: コンテナ再起動
└ environment: DBの設定
└ ports: host 3306番:guest 3306番 ポートで接続
#Dockerfile作成
./laranuxtproj/docker/php に Dockerfile を作成する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
FROM php:7.3-fpm COPY php.ini /usr/local/etc/php/ RUN apt-get update \ && apt-get install -y zlib1g-dev libzip-dev mariadb-client \ && docker-php-ext-install zip pdo_mysql #Composer install COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer ENV PATH $PATH:/composer/vendor/bin WORKDIR /var/www RUN composer global require "laravel/installer" |
#php.iniの作成
./laranuxtproj/docker/php にphp.ini を作成する
1 2 3 4 5 6 |
[Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese" |
#nginx設定ファイル作成
./laranuxtproj/docker/nginx直下に作成する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
server { listen 80; root /var/www/public; index index.php; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { 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; } } |
#MySQLの設定
1 2 3 4 5 6 7 |
[mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci [client] default-character-set=utf8mb4 |
Laravelプロジェクト作成
#起動したコンテナに入りLaravelプロジェクトを作成
1 2 3 4 5 6 |
# docker起動 docker-compose up -d # phpコンテナに入ります docker-compose exec php bash # Laravelプロジェクト作成 laravel new |
#ブラウザで動作確認
ブラウザからlocalhostにアクセスするとLaravelの画面が表示されていれば完了
#MySQLコンテナ確認
1 2 3 4 5 6 7 8 9 |
# mysqlコンテナに入ります docker exec -it db bash mysql -u root -p root //設定ファイルに記載したパスワード //ログインできていれば完了 //以下テーブル作成した際に確認用 show databases; use test_db; show tables; |
Laravel の初期設定
#.envファイルを修正
DB接続情報を書き換える
docker-compose.ymlに記載の情報を.envファイルに追記する
1 2 3 4 |
DB_HOST=db DB_DATABASE=test_db DB_USERNAME=root DB_PASSWORD=root |
上記完了すれば再起動する
1 |
docker-compose restart |
1 |
php artisan migrate |
※これでもできない場合以下で権限を変更する
1 2 |
grant all privileges on test_db.* to 'root'@'localhost'; FLUSH PRIVILEGES; |
#LaravelのテーブルやAppKeyを作成 ,キャッシュもクリアする場合
1 2 3 |
php artisan migrate php artisan key:generate php artisan cache:clear |
#ライブラリのインストール
composer.json にあるライブラリをインストールする必要がある場合
1 |
composer install |
#node.jsをコマンドでインストールする場合
1 2 3 4 |
docker-compose exec php bash // コンテナに入る curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.3/install.sh | bash nvm install -y v12.18.3 nvm alias default v12.18.3 |
NodejsをインストールするコマンドをDockerfileに追加
#Dockerfileに追記する
プロジェクトの開発途中に必要なライブラリなど増えた場合Dockerfileを作り直す。
node.jsインストールコマンドを追記する
1 2 3 4 5 6 7 |
RUN apt-get -y update RUN apt-get install -y \ curl \ gnupg RUN curl -sL https://deb.nodesource.com/setup_11.x | bash - RUN apt-get install -y nodejs RUN npm install npm@latest -g |
Dockerfileを変更したら一度コンテナを停止させ以下コマンドでビルドする
1 |
docker-composer app build |
package.json にあるライブラリをインストールする必要がある場合
※インストールがうまく行かない場合、いったんpackage.jsonを別名で保存しておき
npm init で作成したものに上書きすれば良い
1 |
npm install |
Laravel に認証機能を導入する
#ログイン認証機能の作成
artisan コマンドでログイン機能と新規ユーザー登録機能が一発で作成できる
以下コマンドで /resources/views/auth を作成
1 2 3 4 5 |
composer require laravel/ui php artisan ui vue --auth npm install npm run dev |
#テストデータを自動で挿入する
artisan コマンドで以下の通り実行すると、
database/seeds に作成される
1 2 |
php artisan make:seeder UserSeeder |
artisan コマンドで以下の通り実行すると、
/database/seeds にUserSeeder.phpに作成される
1 |
php artisan make:seeder UserSeeder |
/database/seeds/UserSeeder.php
1 2 3 4 5 |
DB::table('users')->insert([ 'name' => 'Eiji', 'email' => 'eiji@eiji.com', 'password' => bcrypt('eijipass'), ]); |
/database/seeds/DatabaseSeeder.php
1 |
$this->call(UserSeeder::class); //コメントアウトする |
上記完了すれば以下コマンド実行する
1 |
php artisan db:seed --class=UserSeeder<code> |
Laravel sanctum インストール編
Laravel sanctum では以下のことができる
・トークンを使った API認証
・SPAからLaravelの組み込みCookieベースのセッション認証サービスを使用して認証することができる
#インストール
1 |
composer require laravel/sanctum |
インストールが完了後以下のコマンドで必要なファイルをコピー
1 |
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" |
ファイルが作成されたのでマイグレーションを実行
1 |
php artisan migrate |
Laravel sanctum トークンを使ったAPI認証編
#参考サイト
https://blog.capilano-fw.com/?p=6121
#アクセストークンの作成
UserモデルにHasApiTokensをセットしてトークンを使えるようにする
1 2 3 4 5 6 7 8 |
<?php // 省略 use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use Notifiable, HasApiTokens; // 省略 } |
santumでアクセストークンを作成する
/routes/web.php
1 2 3 4 5 |
Route::get('/create_token', function(){ $user = \App\User::find(1); $token = $user->createToken('my-api-token'); echo $token->plainTextToken; // トークンを表示 }); |
上記の修正完了後に以下URLをブラウザで実行すると
http://localhost/create_token
2|0W8S8wN9K5powOArBrLYRxWkL1aarnkVGRM6qUtUB3lKjRSpwVnhwhnxdvq2Met2hRhcUCuMHQIyhslb
ブラウザにアクセストークンが表示されれば成功(冒頭の『2|』は除く)
データベースを確認して、データも正しく挿入されていることを確認する
1 |
select * from personal_access_tokens; |
#ユーザー情報を取得する使い方
/routes/api.php
1 2 3 4 5 6 |
Route::middleware('auth:sanctum')->group(function(){ // ここは全て「sanctum」のミドルウェアが適用される Route::get('/user', function(Request $request){ return $request->user(); }); }); |
・トークンが正しければユーザー情報を返す
・それ以外は拒否(もしくはリダイレクト)する
上記の実装が可能となる
#POSTMANでテスト
https://www.postman.com/downloads/
アプリをダウンロードしてアカウントを新規に作成する(Googleアカで作成できる)
作成完了後管理画面の上部にある+タブで送信画面を表示
URLに入力してSENDボタンで送信テストができる
#TOKENを指定しない場合
GET : http://localhost/api/user
ページがリダイレクトしてアクセス拒否されれば想定通り
#TOKENを指定した場合
Authorization > Bearer Token に先ほどブラウザに表示されたトークンを入力してアクセス
GET : http://localhost/api/user
TOKEN : 0W8S8wN9K5powOArBrLYRxWkL1aarnkVGRM6qUtUB3lKjRSpwVnhwhnxdvq2Met2hRhcUCuMHQIyhslb
成功すればuser情報が表示される
Laravel sanctum CookieベースのAPI認証編(Nuxt.js)
#説明
同一オリジン内でのAPIアクセスを想定している
Nuxt.jsはport 3000で動作させてAPIにアクセスする際は、
はじめにセッションを取得して
#起動したコンテナに入りNuxt.jsプロジェクトを作成
1 2 3 4 5 6 |
# docker起動 docker-compose up -d # uiコンテナに入ります docker-compose exec ui bash # nuxtプロジェクト作成 npx create-nuxt-app nuxt |
※npx での作成がうまく行かなかった場合以下を実行する
1 |
npm config set unsafe-perm true |
以下のように選択
Generating Nuxt.js project in nuxt
Project name: nuxt
Programming language: JavaScript
Package manager: Npm
UI framework: Vuetify.js
Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
Testing framework: None
Rendering mode: Universal (SSR / SSG)
Deployment target: Server (Node.js hosting)
Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
#package.jsonにポート3000でアクセスできるように設定
末尾に以下を追記する
1 2 3 4 5 6 |
"config": { "nuxt": { "host": "0.0.0.0", "port": "3000" } } |
#Laravel側にNuxt.jsからのアクセスを許可する設定を行う
Nuxt.jsが起動するドメインを追記する
./config/sanctum.php
1 |
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost:8000,localhost:8080,127.0.0.1,127.0.0.1:8000,127.0.0.1:8080,::1')), |
Sanctumを使用してSPAを認証する場合ファイル内のミドルウェアグループにSanctumのミドルウェアを追加する
./app/Http/Kernel.php
1 2 3 4 5 6 |
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful; 'api' => [ EnsureFrontendRequestsAreStateful::class, 'throttle:60,1', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], |
#Laravel sanctum で認証できるログイン画面を作成
./nuxt/pages/login.vue を作成する
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<template> <div> <label class="block">メールアドレス</label> <input type="text" class="border border-gray-900" v-model="email"/> <br> <label class="block">パスワード</label> <input type="password" class="border border-gray-900" v-model="password"/> <br> <br> <button v-on:click="login()" class="cursor border border-gray-900 p-2">ログイン</button> </div> </template> ~ 以下続く ~ |
axiosモジュールを使い /sanctum/csrf-cookieルートを呼び出し認証に使用されるXSRF-COOKIEが設定される
withCredentials: true、リクエストにCookieが確実に渡されるように設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<script> export default { data(){ return { email: '', password: '' } }, methods: { login(){ this.$axios.get('/sanctum/csrf-cookie', { headers: { 'X-Requested-With': 'XMLHttpRequest' }, withCredentials: true, }) .then( <span class="hljs-function">function(){ this.$auth.loginWith('local', { data: { email: this.email, password: this.password }, }); }.bind(this)) } } } </script></span> |
#authモジュールをインストール
Laravel sanctumを使うためにはAxiosとauthモジュールをインストールする必要がある
AxiosはNuxtをインストールする際の選択で選んでいるものとして以下authをインストール
1 2 |
cd nuxt npm install @nuxtjs/auth |
nuxtjs/authの型ファイルもインストール
1 |
npm install --save-dev @types/nuxtjs__auth |
./nuxt.config.jsに追加したモジュールを追記する
1 2 3 4 |
modules: [ '@nuxtjs/axios', '@nuxtjs/auth' ], |
#authモジュールの構成
./nuxt.config.jsを以下のように追記する
【auth:】auth認証モジュールがAPIを操作するために使用するキーを構成に作成する
【login:】 ログイン資格情報を送信するエンドポイント /loginURLへのPOSTリクエスト
withCredentials: true で、cookie(クレデンシャル)を渡す許可
HTTPリクエストを作成して、jsonデータを送信する
【user:】 ログインしたユーザーを取得するルートを設定 GETリクエスト
tokenRequired: false, // Tokenを使用しない為、falseとする
tokenType: false // Tokenを使用しない為、falseとする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
... auth: { strategies: { local: { endpoints: { login: { url: '/login', method: 'post', withCredentials: true, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' } }, user: { url: '/api/user', method: 'get', propertyName: false, withCredentials: true, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' } } }, tokenRequired: false, tokenType: false } } }, ... |
#AxiosリクエストのベースURLを設定
./nuxt.config.jsを以下のように追記する
1 2 3 |
axios: { baseURL: 'http://nuxtjslaravel.test/' }, |
#CORSライブラリをインストール
SPAやモバイルアプリなど他のオリジンからAPIにアクセスするにはCORSライブラリをインストールする必要がある
※CORS (オリジン間リソース共有、 Cross-Origin Resource Sharing) は、 HTTP ヘッダーの転送で構成されるシステムであり、ブラウザーがオリジンをまたいだリクエストのレスポンスに、フロントエンドの JavaScript コードがアクセスすることをブロックするかどうかを決めるもの
1 2 |
composer require fruitcake/laravel-cors |
グローバルHTTPミドルウェアの最後にミドルウェアを追加する
./app/Http/Kernel.php
1 2 3 4 5 |
protected $middleware = [ ~ 省略 ~ \Fruitcake\Cors\HandleCors::class, ]; |
以下コマンドを実行することにより、SanctumがNuxtで動作するようにカスタマイズできる
1 2 |
php artisan vendor:publish --tag="cors" |
./config/cors.php のpath キーに追記
‘sanctum/csrf-cookie’, ・・・ Laravel SanctumでCSRF Cookieを受け取るために使用するルート
‘login’, ・・・ /loginルートへのPOSTリクエスト
デフォルトのLaravel Auth(1分でセットアップされます)によって処理される
‘api/*’ ・・・ SPA、モバイル、またはデスクトップアプリからCORSを介してすべてのAPIルートにアクセスできる
1 2 3 4 5 6 |
'paths' => [ 'sanctum/csrf-cookie', 'login', 'api/*' ], |
CORSが有効なルートに認証リクエストを送信するため、
Access-Control-Allow-Credentialsヘッダーを追加するための設定を有効にする必要があります
Axiosではこのヘッダーが有効でアクセス可能である必要があり、
このヘッダーを有効にするには、supports_credentialsキーfalse
を次のtrue
ように変更します
1 |
'supports_credentials' => true, |
最後に
Dockerを使うと簡単に環境を作れるのでかなり便利
実際に今の現場や求人など見てもDockerを使うのは必須になっているようなので覚えるべき
ただ案外簡単にできるのですぐにでもやるべき