目的#
Dockerで構築したローカルの開発環境を基に、
アプリケーションをHerokuへデプロイしたい。
Herokuの機能を使用して、
GitHubのリモートリポジトリへPushしたら自動でHerokuのデプロイが走るようにしたい。
参考#
上記の記事を参考にいたしました。
環境#
以下の環境をDockerを使ってローカル上に構築しています。
サービス | 名前 | バージョン |
---|---|---|
Webサーバー | nginx | 1.15.6 |
フロントエンドFW | VueJS | vue@2.6.14 |
バックエンドFW | Laravel | 7.30.5 (php:7.2-fpm) |
データベース | PostgreSQL | latest(psql (PostgreSQL) 14.1 (Debian 14.1-1.pgdg110+1))] |
データベースGUI | PG Admin | 4 |
事前準備#
・Herokuへの登録
・Heroku CLIのインストール
・GitHubへの登録
設定ファイル#
に今回使用する設定ファイルを置いています。
開発環境構築(Nginx, Laravel, PostgresSQL)#
git clone https://github.com/roughstorm/dnlvp
cd dnlvp
docker-compose up --build -d
docker-compose exec app bash
リポジトリからクローンした設定ファイルを基にDocker-composeでDocker上に環境構築し、appコンテナ内に入る。
上記の設定ファイルを使用する場合は、以下の事項に注意してください。
ローカルでのDockerコマンド実行前に、docker-compose.yml
内のpgadmin
のenvironment
のPGADMIN_DEFAULT_EMAIL
のメールアドレスを適宜変更してください。
docker/web/default.conf
内にてrootをroot /var/www/html/[dnlvp]/public;
と指定しています。
作成するLaravelのプロジェクト名(フォルダ名)に合わせて[dnlvp]の部分を変更してください。
composer create-project --prefer-dist laravel/laravel dnlvp
cd dnlvp/
chmod -R 777 storage
composerコマンドで新しいLaravelプロジェクトを作成し、
storageフォルダに権限を付与(log出力のエラーが出るため)
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=sample
DB_USERNAME=user
DB_PASSWORD=password
Laravelプロジェクト作成時にできる環境設定ファイル(.env
)にPostgresSQL用の環境変数をセットする。
php artisan migrate
php artisan migrate
で、DBのマイグレーションを行っておく。
VueJSのインストール#
composer require laravel/ui
php artisan ui vue
npm install
npm install -D vue
npm install --save vue-router
npm list vue
npm run dev
npm audit fix
npm run watch
composer require laravel/ui
のコマンドでLaravelでVue(Reactも)を使うためのライブラリをインストールします。
php artisan ui vue
コマンドでvue用のスカフォールドを設定します。
npm
コマンドnodejsのコマンドです。
npm install
コマンドについては、下記のサイトが参考になりました。
npm list vue
コマンドで、バージョンが返ってくればvueがインストールされています。
npm run watch
コマンドまで実行したら、動作を確認します。
ローカルでの動作確認#
まず、動作確認用に以下のファイルを編集/作成します。
dnlvp/routes/web.php
dnlvp/resouces/views/app.blade.php
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/{any}', function() {
return view('app');
})->where('any', '.*');
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Vue Laravel SPA') }}</title>
<!-- Styles -->
<link href="{{ mix('/css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<example-component></example-component>
</div>
<!-- Scripts -->
<script src="{{ mix('/js/app.js') }}" defer></script>
</body>
</html>
上記のファイルを更新/作成した状態で、localhost:8000にアクセスし、以下の画面のように動作が確認できると思います。
.gitignoreの設定#
コンパイル済みファイルである、/public/js
と/public/css
はgit管理する必要がないのでgitignoreに追記しておきます。
これらのファイルは、Herokuではデプロイ時にまた作成されるようです。
/public/js
/public/css
Herokuへのデプロイ#
下記コマンドを実行する前に、カレントディレクトリをLaravelのプロジェクトフォルダに移動しておいてください。
Herokuアプリの作成#
heroku login
heroku create dnlvp
heroku login
でHerokuにログインします。ブラウザが開いて認証します。
heroku create
で新しいHerokuアプリを作成します。 dnlvp
がアプリ名になります。既に同じ名前のアプリがあると作成できません。(testとかはすでにとられてます。)
GitHubリポジトリの準備#
今回は、Herokuの機能を使用して、GitHub上のリモートリポジトリにPushしたらHerokuにもデプロイが走るようにしたいので、まずGitHubにHerokuアプリ用のリポジトリを作成します。
今回は、https://github.com/roughstorm/dnlvponheroku.gitというリポジトリを作成しました。
HerokuとGitHubで連携をする場合は、リポジトリが空だと連携出来ないと表示されるので、まず先にリポジトリ内にファイルをいれます。
echo "It's a practice for deploy on Heroku." >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/roughstorm/dnlvponheroku.git
git push -u origin main
これらのコマンドは、カレントディレクトリをLaravelのプロジェクトフォルダに移動してから実行してください。(.envなどがあるフォルダ)
HerokuとGitHubを連携させて自動デプロイの設定#
https://jp.heroku.com にログインし、作成したプロジェクトを選びます。
Deployment methodでGitHubを選択します。
Github上のリポジトリを検索するテキストボックスが出るので、自身の設定したリポジトリ名を検索して、適用したいリポジトリを選んでConnectを押します。
まだこの状態ではPushしただけで自動でデプロイが走るようにはなっていません。
HerokuとリポジトリのConnectが完了すると、Automatic deploysという項目ができて、Enable Automatic Deploysというボタンが出ますので、こちらを押すことによって自動デプロイの設定が完了します。
Heroku側のBuildpacks(PHPとNodeJS)の設定#
Heroku側での設定をしていきます。
なお、下記Herokuコマンドは -a
で自身のアプリ名を指定しないと動きません。
heroku buildpacks:set heroku/php -a dnlvp
heroku buildpacks:add heroku/nodejs -a dnlvp
buildpacks(アプリがデプロイされる際に実行されるスクリプト)の設定をします。
LaravelとVueを使うので、phpとnodejsをセットします。
ちなみに、 上画像のように https://jp.heroku.com
にログインし、アプリを選択した後、Settingsのタブからもbuildpacksの設定、確認を行うことができます。
Heroku側のPostgresSQLの設定#
heroku addons:create heroku-postgresql:hobby-dev -a dnlvp
addonにPostgresSQLを追加します。
こちらも、https://jp.heroku.com
からログインし、アプリを選択した後、Resourcesのタブから設定や確認ができます。
heroku config:get DATABASE_URL -a dnlvp
addonにPostgreSQLを追加すると、自動で環境変数にDATABASE_URLが追加されるので、そちらを取得し、Herokuへ設定していきます。
heroku config:get DATABASE_URL
を実行すると、以下の形式で返ってきますので、これらを基に対応する値をHerokuへ設定していきます。
postgres://<ユーザ名>:<パスワード>@<ホスト>:5432/
heroku config:set DB_CONNECTION=pgsql -a dnlvp
heroku config:set DB_HOST=<ホスト> -a dnlvp
heroku config:set DB_DATABASE=<DB名> -a dnlvp
heroku config:set DB_USERNAME=<ユーザ名> -a dnlvp
heroku config:set DB_PASSWORD=<パスワード> -a dnlvp
こちらも、https://jp.heroku.com
からログインし、アプリを選択した後、SettingsのタブのConfig Varsから設定や確認ができます。
Laravelの環境変数の設定#
heroku config:set APP_ENV=production -a dnlvp
heroku config:set APP_DEBUG=false -a dnlvp
heroku config:set APP_URL=https://dnlvp.herokuapp.com/ -a dnlvp
Laravelで使用するAPP_ENVなどの環境変数を設定します。
APP_URL=https://dnlvp.herokuapp.com/
については、自身のアプリのURLを指定してください。
Procfile, nginx.confの追加#
Laravelプロジェクトのフォルダに、下記のファイルを新規作成します。
Procfile
nginx.conf
web: vendor/bin/heroku-php-nginx -C nginx.conf public/
Procfile
はアプリケーションがどのプロセスを使うのか宣言するためのファイルだそうです。
web: vendor/bin/heroku-php-nginx
によってnginxを使用することを指定し、
-C nginx.conf
で、同じフォルダ内にある nginx.confファイルを参照することを指定、
public/
でドキュメントルートの指定をしています。
また、Procfile
はファイル名が決まっているので大文字(PROCFILE)とか小文字(procfile)だと動きませんでした。
location / {
try_files $uri @rewriteapp;
}
location @rewriteapp {
rewrite ^(.*)$ /index.php$1 last;
}
location / {~ ~}
にて、アクセスしたURLのファイルがあるかどうかを確認し、あればそのファイルを返し、なければ@rewriteappロケーションに行きます。
location @rewriteapp{~ ~}
にて、送られてきたURI応じて、index.php[正規表現に一致する部部分]として書き換え、lastがあるので、location / {~ ~}
の処理から、また一致するかどうかを確認していく、と思います。
今回デプロイするHerokuのアプリでは、アプリのURLにアクセスすると,Procfile
に設定したpublic/
へ行き、nginx.confの処理によってpublic/index.php
が戻ってくることによって、アプリへアクセスが出来るということになると思います。
下記の記事を参考にいたしました。
package.json, composer.jsonの編集#
下記のファイルを編集します。
package.json
composer.json
"heroku-postbuild": "npm run prod"
package.json
内の"scripts"
要素の中に、"heroku-postbuild": "npm run prod"
を追加します。
これをいれないと、Heroku上でnpm run buildがされないので、vueが使えません。
"scripts"
要素内に追加する際に、最後の行に入れる場合は、上行の改行の前に,
を入れないと、ファイルを読んだ際にエラーが出ます。
"require": {
"php": "^7.2.5|^8.0",
"ext-intl": "*",
"fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
"laravel/framework": "^7.29",
"laravel/tinker": "^2.5",
"laravel/ui": "^2.5"
},
composer.json
内のrequire
要素内に"ext-intl": "*",
を追加します。
intl(国際化用拡張モジュール)を使用できるようにする為に必要です。
PHPで国際化用に使うライブラリの様です。
これらが具体的にどんな動作をするのかまではまだわかっていません・・すいません。
https強制化#
こちらの記事を参考にいたしました。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
// 本番環境(Heroku)でhttpsを強制する
if (\App::environment('production')) {
\URL::forceScheme('https');
}
}
}
まず、ローカル環境のapp/Providers/AppServiceProvider.php
を上記の様に変更します。
docker-compose exec app bash
cd dnlvp/
php artisan make:middleware ForceHttpToHttps
Laravelのミドルウェアを作るため、コンテナ内に入り、
Laravelプロジェクトのフォルダでphp artisan make:middleware ForceHttpToHttps
を実行します。
<?php
namespace App\Http\Middleware;
use Closure;
class ForceHttpToHttps
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (\App::environment(['staging', 'production']) && $_SERVER["HTTP_X_FORWARDED_PROTO"] != 'https') {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
php artisan make:Middleware
で自動的にForceHttpToHttps.php
が作成されますので、
app/Http/Middleware/ForceHttpToHttps.php
を上記の様に書き換えます。
(省略)
protected $middleware = [
(省略)
\App\Http\Middleware\ForceHttpToHttps::class, // 追加
];
(省略)
app/Http/Middleware/Kernel.php
に上記を追加します。
また、これらの変更を加えた時点でローカル環境に異常が発生していないか確認をしたほうがよいと思います。
デプロイ#
git add .
git commit -m "initial commit"
git branch -M main
git push -u origin main
Laravelプロジェクトのフォルダで一度、上記を実行します。
これで一度Heroku上でデプロイが走ると思いますが、
設定していない項目がありますので、まだアプリは動きません。
APP_KEYの設定#
heroku run php artisan key:generate --show -a dnlvp
heroku config:set APP_KEY='{ここに上記で生成されたAPP_KEY(base64から始まる文字列)をコピペ}' -a dnlvp
上記コマンドでAPP_KEYの設定をします。
APP_KEY=$(php artisan key:generate --show)
で設定している記事を多くみかけましたが、私の環境からだと何度やってもAPP_KEYに空が設定されてしまうので、この様にしております。
DBのマイグレーション・シーディング#
heroku run php artisan migrate --seed -a dnlvp
上記を実行します。
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
>
既にアプリケーションが動いている状態ですので、ほんとにマイグレーションしていいの?と聞かれますので、Yesでマイグレーションを実行します。
動作確認#
自身のアプリのURLにアクセスし、動作を確認します。
Heroku上に構築された環境で、Vueのコンポーネントが表示されました。
おわりに#
突貫な感じで恐縮ですが、開発から本番までの環境を作ることができてよかったです。
技術から別の技術へいろいろと派生していき、これを調べたらあれも調べないと、
みたいな感じで調査に時間がかかってしまうので、勉強不足を痛感しました。
技術的に拙い部分が多くあって怖いですが、
とりあえず環境ができたので実装のほうをやっていきたいと思っています。
内容について、やってはいけない感じのことをやっていたり、
こうしたほうがよいなどのご助言がありましたら、お教え頂けますと幸いです。
追記2021/11/23#
私の環境だとこれで構築したDocker内の環境では、
npm run watch, npm run watch -pollともになぜか正常に動作しません。
ファイルの変更をキャッチして勝手にビルドしてくれないのです。なぜだい。
たぶん、webpack.mix.jsあたりに何かありそうな気がするんですが、頭が働いてくれませんでした。
なので、jsやvueを変えたら都度npm run devしてください。悲しみ。