そもそもの話
最近、Laradock触ってないなぁ、と思ったので、試しにDuskを動かそうと思ったことから始まりました。
環境はすでに作成しているものを使っています。
やってみたいこと
- Laravelをサブディレクトリとして構築
- Duskのテストが通る
とりあえずの前提条件
- Webサーバのrootとしては、
/var/www/public
を指定 - Laravelのrootは
/var/www/public/lara1
、URLもhttp://localhost/lara1
でアクセスできるようにする - 他の設定は標準(Seleniumアクセスのポートは4444で、など)
Laradock起動コマンド
Webサーバはnginx、データベースはmysqlを使います。
Chromeはseleniumコンテナに入っているので同時に起動します。
あとは適当に
docker-compose up workspace nginx mysql selenium
Dusk導入まで
やり方は2つの参考記事をもとに対応。
参考1: https://qiita.com/amymd/items/0a5f2705e29972d0d22e
参考2: https://qiita.com/hrkbyc/items/755e9799c205c092c323
コマンドは以下の順番で処理していきます。
cd /var/www/public
composer create-project laravel/laravel lara1 --prefer-dist
cd lara1
composer install
composer require --dev dusk
composer update # 念の為
npm install
npm run dev
php artisan dusk:install
キモは、
AppServiceProvider.phpの修正
Duskをプロバイダに登録するコードを追加します。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Laravel\Dusk\DuskServiceProvider; // Duskの参照を追加
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
// Duskのプロバイダを登録
if ($this->app->environment('local', 'testing')) {
$this->app->register(DuskServiceProvider::class);
}
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
DuskTestCase.php の修正
baseUrlを所定のURLに、driverをSeleniumのサーバーに変更します。
<?php
namespace Tests;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Laravel\Dusk\TestCase as BaseTestCase;
abstract class DuskTestCase extends BaseTestCase
{
use CreatesApplication;
// baseUrlは別サーバのサブディレクトリになるため明記
protected function baseUrl()
{
return 'http://nginx/lara1';
}
/**
* Prepare for Dusk test execution.
*
* @beforeClass
* @return void
*/
public static function prepare()
{
if (! static::runningInSail()) {
static::startChromeDriver();
}
}
/**
* Create the RemoteWebDriver instance.
*
* @return \Facebook\WebDriver\Remote\RemoteWebDriver
*/
// seleniumコンテナのChromeを使用する
protected function driver()
{
return RemoteWebDriver::create(
'http://selenium:4444/wd/hub',
DesiredCapabilities::chrome()
);
}
/**
* Determine whether the Dusk command has disabled headless mode.
*
* @return bool
*/
protected function hasHeadlessDisabled()
{
return isset($_SERVER['DUSK_HEADLESS_DISABLED']) ||
isset($_ENV['DUSK_HEADLESS_DISABLED']);
}
}
さあテスト開始…ところが!?
php artisan dusk
ところが、エラーを出してしまうわけです。
Duskはちゃんと動いているようですが、どうやらLaravelのアプリがまともに動いていないと予想しました。
そこで、参考記事を元にnginxの設定をいじることにしました。
参考:https://qiita.com/saba1024/items/2d50fb8284d699924360
対策とってみた
default.confの設定変更
vi /etc/nginx/sites-available/default.conf
先の記事で参照していたnginxの設定ではサブディレクトリを考慮していなかったので、色々設定を変えました。
最終的にはこういう形になりました。
特にハマったのはSCRIPT_FILENAME。
index.phpの場所が変わっているのにすぐに気づきませんでした…。
パスの指定を現在の配置に合わせました。
fastcgi_param SCRIPT_FILENAME $document_root/public/index.php;
あと、fastcgi_passの指定。
もともとあったLaravel向けの設定を読んでみて、php-upstreamコンテナを指定すれば良いことがわかりました。
fastcgi_pass php-upstream;
あとは、locationやtry_filesの設定に注意して出来上がりました。
location ~ ^/lara1((/)?(.+))?$ {
root /var/www/public/lara1;
try_files $1 /lara1/index.php?$query_string;
location ~ ^/lara1/index.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/public/index.php;
fastcgi_param PATHINFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-upstream;
fastcgi_index index.php;
}
}
そして、nginxの再起動…エラーなし。
nginx -s reload
これでLaravelが動くだろう…世の中そんなに甘くありませんでした。
書き込み権限の変更
…Dockerのコマンドラインではrootなのに、nginx上ではnginxユーザで動かしているのをすっかり忘れていました。
storageディレクトリに書き込み権限を付記します。
cd /var/www/public/lara1
chmod -R a+w storage
さあリベンジ!
ブラウザでは無事Laravelのアプリが表示されました。
続いてDuskでは…
root@6580d8cd10f5:/var/www/public/lara1# php artisan dusk
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 00:10.353, Memory: 20.00 MB
OK (1 test, 1 assertion)
動いたー! やったー!
まとめ
過去の知見となんとか駆使すればなんとかなるということです、はい。