概要
Laravel Sail のドキュメントを見ると、php コマンドと composer コマンドが導入されていることが前提で説明されています。
ですが、私のローカルPCの環境には Laravel が動作するために必要な以下のコマンド群を導入してません。
phpcomposerlaravel/installer-
node/npm/npx yarn
ということで、本記事ではこれらのコマンドをインストールせずに Laravel Sail を動かしてみようと思います。
動作検証環境
- Ubuntu: 22.04
$ grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
- Docker: 29.2.0
$ docker --version
Docker version 29.2.0, build 0b9d198
Laravel のインストール方法について
Laravel のアプリケーションを作成する場合、 laravel new example-app のようなコマンドを実行しますが、前述のとおり laravel コマンドがインストールされていません。
なので composer create-project laravel/laravel example-app を実行したいわけですが、 composer コマンドもインストールされていません。
そこで、今回は Composer の Docker Official Imageを利用します。
Laravel のアプリケーションを作成する際、前述のとおり以前であれば以下のようなコマンドを実行していました。
$ composer create-project laravel/laravel example-app
しかし、公式のインストールガイドでは、こちらの手順のみが掲載されています。
$ composer global require laravel/installer
$ laravel new example-app
laravel new example-app が何を行っているのかを追っていくと、結局は composer create-project laravel/laravel example-app だとわかります。
なので、以下のように Composer の Docker イメージを利用して実行することもできます。
$ docker container run \
--rm \
-u $(id -u):$(id -g) \
-v $(pwd):/app \
-it composer:latest \
composer create-project laravel/laravel my-laravel-sail
今回は、以下のように Composer の Docker コンテナ内で laravel/installer をインストールして laravel コマンドを実行してみます。
$ docker container run \
--rm \
-u $(id -u):$(id -g) \
-v $(pwd):/app \
-it composer:latest \
sh -c "composer global require laravel/installer \
&& export PATH=\$PATH:/tmp/vendor/bin \
&& laravel new my-laravel-sail"
/tmp/vendor/bin に対してパスを通している理由は、 Composer の Docker イメージで COMPOSER_HOME が /tmp になっているためです。
これにより /tmp/vendor/bin/laravel ではなく laravel で実行可能となります。
Laravel のインストール
それでは先程紹介した Laravel のインストールコマンドを参考にしつつ、 node と npm コマンドも利用可能な形で実行します。
$ cd /PATH_TO/作業ディレクトリ
$ docker container run \
--rm \
-v $(pwd):/app \
-it composer:latest \
sh -c "
apk add --no-cache nodejs npm \
&& composer global require laravel/installer \
&& export PATH=\$PATH:/tmp/vendor/bin \
&& laravel new my-laravel-sail \
&& chown -R $(id -u):$(id -g) my-laravel-sail
"
まず、 starter kit の選択肢が表示されますので、今回は None を選択します。
(1/7) Installing ada-libs (3.3.0-r0)
(2/7) Installing icu-data-en (76.1-r1)
Executing icu-data-en-76.1-r1.post-install
*
* If you need ICU with non-English locales and legacy charset support, install
* package icu-data-full.
*
(3/7) Installing icu-libs (76.1-r1)
(4/7) Installing simdjson (3.12.0-r0)
(5/7) Installing simdutf (7.5.0-r1)
(6/7) Installing nodejs (24.13.0-r1)
(7/7) Installing npm (11.6.3-r0)
Executing busybox-1.37.0-r30.trigger
OK: 169.3 MiB in 93 packages
Changed current directory to /tmp
./composer.json has been created
Running composer update laravel/installer
Loading composer repositories with package information
Updating dependencies
Lock file operations: 32 installs, 0 updates, 0 removals
- Locking carbonphp/carbon-doctrine-types (3.2.0)
- Locking doctrine/inflector (2.1.0)
- Locking illuminate/collections (v12.52.0)
・
・
省略
・
・
- Installing symfony/finder (v7.4.5): Extracting archive
- Installing illuminate/filesystem (v12.52.0): Extracting archive
- Installing laravel/installer (v5.24.6): Extracting archive
22 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
20 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
Using version ^5.24 for laravel/installer
██╗ █████╗ ██████╗ █████╗ ██╗ ██╗ ███████╗ ██╗
██║ ██╔══██╗ ██╔══██╗ ██╔══██╗ ██║ ██║ ██╔════╝ ██║
██║ ███████║ ██████╔╝ ███████║ ██║ ██║ █████╗ ██║
██║ ██╔══██║ ██╔══██╗ ██╔══██║ ╚██╗ ██╔╝ ██╔══╝ ██║
███████╗ ██║ ██║ ██║ ██║ ██║ ██║ ╚████╔╝ ███████╗ ███████╗
╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚══════╝ ╚══════╝
┌ Which starter kit would you like to install? ────────────────┐
│ › ● None │
│ ○ React │
│ ○ Svelte │
│ ○ Vue │
│ ○ Livewire │
└──────────────────────────────────────────────────────────────┘
testing framework の選択肢が表示されますので、今回は PHPUnit を選択します。
┌ Which starter kit would you like to install? ────────────────┐
│ None │
└──────────────────────────────────────────────────────────────┘
┌ Which testing framework do you prefer? ──────────────────────┐
│ ○ Pest │
│ › ● PHPUnit │
└──────────────────────────────────────────────────────────────┘
AIアシスタントである Laravel Boost のインストールが必要か求められますので、今回は No を選択します。
┌ Which starter kit would you like to install? ────────────────┐
│ None │
└──────────────────────────────────────────────────────────────┘
┌ Which testing framework do you prefer? ──────────────────────┐
│ PHPUnit │
└──────────────────────────────────────────────────────────────┘
┌ Do you want to install Laravel Boost to improve AI assisted coding? ┐
│ ○ Yes / ● No │
└─────────────────────────────────────────────────────────────────────┘
データベースの選択肢が表示されますので、今回は SQLite を選択します。
┌ Which starter kit would you like to install? ────────────────┐
│ None │
└──────────────────────────────────────────────────────────────┘
┌ Which testing framework do you prefer? ──────────────────────┐
│ PHPUnit │
└──────────────────────────────────────────────────────────────┘
┌ Do you want to install Laravel Boost to improve AI assisted coding? ┐
│ No │
└─────────────────────────────────────────────────────────────────────┘
Creating a "laravel/laravel" project at "./my-laravel-sail"
Installing laravel/laravel (v12.11.2)
- Downloading laravel/laravel (v12.11.2)
- Installing laravel/laravel (v12.11.2): Extracting archive
Created project in /app/my-laravel-sail
Loading composer repositories with package information
Updating dependencies
Lock file operations: 111 installs, 0 updates, 0 removals
- Locking brick/math (0.14.8)
- Locking carbonphp/carbon-doctrine-types (3.2.0)
- Locking dflydev/dot-access-data (v3.0.3)
・
・
省略
・
・
- Installing phar-io/manifest (2.0.4): Extracting archive
- Installing myclabs/deep-copy (1.13.4): Extracting archive
- Installing phpunit/phpunit (11.5.55): Extracting archive
70 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating optimized autoload files
81 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
INFO Application key set successfully.
┌ Which database will your application use? ───────────────────┐
│ › ● SQLite │
│ ○ MySQL (Missing PDO extension) │
│ ○ MariaDB (Missing PDO extension) │
│ ○ PostgreSQL (Missing PDO extension) │
│ ○ SQL Server (Missing PDO extension) │
└──────────────────────────────────────────────────────────────┘
npm install と npm run build の実行を求められますので、今回は Yes を選択します。
┌ Which database will your application use? ───────────────────┐
│ SQLite │
└──────────────────────────────────────────────────────────────┘
INFO Preparing database.
Creating migration table ...................................... 28.19ms DONE
INFO Running migrations.
0001_01_01_000000_create_users_table ......................... 106.30ms DONE
0001_01_01_000001_create_cache_table .......................... 67.00ms DONE
0001_01_01_000002_create_jobs_table ........................... 91.32ms DONE
┌ Would you like to run npm install and npm run build? ────────┐
│ ● Yes / ○ No │
└──────────────────────────────────────────────────────────────┘
以上で Laravel のインストール作業は完了となります。
┌ Would you like to run npm install and npm run build? ────────┐
│ Yes │
└──────────────────────────────────────────────────────────────┘
added 82 packages, and audited 83 packages in 10s
21 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
> build
> vite build
vite v7.3.1 building client environment for production...
✓ 53 modules transformed.
public/build/manifest.json 0.33 kB │ gzip: 0.16 kB
public/build/assets/app-Cg9bk4C0.css 34.04 kB │ gzip: 8.47 kB
public/build/assets/app-CKl8NZMC.js 36.69 kB │ gzip: 14.71 kB
✓ built in 443ms
INFO Application ready in [my-laravel-sail]. You can start your local development using:
➜ cd my-laravel-sail
➜ composer run dev
New to Laravel? Check out our documentation. Build something amazing!
実行ユーザーと作成された Laravel のアプリケーションのディレクトリの所有者が一致していることを確認します。
$ echo $USER
akase244
$ ls -ld my-laravel-sail/
drwxr-xr-x 13 akase244 akase244 4096 2月 23 13:35 my-laravel-sail/
Laravel アプリケーションのディレクトリ内に以下のようなファイル群が作成されました。
$ cd my-laravel-sail
$ ls -la
合計 492
drwxr-xr-x 13 akase244 akase244 4096 2月 23 13:35 .
drwxrwxr-x 121 akase244 akase244 4096 2月 23 13:31 ..
-rw-r--r-- 1 akase244 akase244 252 1月 20 02:57 .editorconfig
-rw-r--r-- 1 akase244 akase244 1142 2月 23 13:33 .env
-rw-r--r-- 1 akase244 akase244 1086 2月 23 13:33 .env.example
-rw-r--r-- 1 akase244 akase244 186 1月 20 02:57 .gitattributes
-rw-r--r-- 1 akase244 akase244 283 1月 20 02:57 .gitignore
-rw-r--r-- 1 akase244 akase244 3911 1月 20 02:57 README.md
drwxr-xr-x 5 akase244 akase244 4096 1月 20 02:57 app
-rwxr-xr-x 1 akase244 akase244 425 1月 20 02:57 artisan
drwxr-xr-x 3 akase244 akase244 4096 1月 20 02:57 bootstrap
-rw-r--r-- 1 akase244 akase244 2869 2月 23 13:33 composer.json
-rw-r--r-- 1 akase244 akase244 309333 2月 23 13:31 composer.lock
drwxr-xr-x 2 akase244 akase244 4096 1月 20 02:57 config
drwxr-xr-x 5 akase244 akase244 4096 2月 23 13:33 database
drwxr-xr-x 77 akase244 akase244 4096 2月 23 13:35 node_modules
-rw-r--r-- 1 akase244 akase244 93952 2月 23 13:35 package-lock.json
-rw-r--r-- 1 akase244 akase244 414 1月 20 02:57 package.json
-rw-r--r-- 1 akase244 akase244 1284 1月 20 02:57 phpunit.xml
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 public
drwxr-xr-x 5 akase244 akase244 4096 1月 20 02:57 resources
drwxr-xr-x 2 akase244 akase244 4096 1月 20 02:57 routes
drwxr-xr-x 5 akase244 akase244 4096 1月 20 02:57 storage
drwxr-xr-x 4 akase244 akase244 4096 1月 20 02:57 tests
drwxr-xr-x 39 akase244 akase244 4096 2月 23 13:32 vendor
-rw-r--r-- 1 akase244 akase244 436 1月 20 02:57 vite.config.js
node_modules ディレクトリ内に以下のように npm のパッケージがインストールされていることを確認します。
$ ls -la node_modules/
合計 360
drwxr-xr-x 77 akase244 akase244 4096 2月 23 13:35 .
drwxr-xr-x 13 akase244 akase244 4096 2月 23 13:35 ..
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 .bin
-rw-r--r-- 1 akase244 akase244 50085 2月 23 13:35 .package-lock.json
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 .vite-temp
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 @esbuild
drwxr-xr-x 7 akase244 akase244 4096 2月 23 13:35 @jridgewell
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 @rollup
drwxr-xr-x 6 akase244 akase244 4096 2月 23 13:35 @tailwindcss
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 @types
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 ansi-regex
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 ansi-styles
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 asynckit
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 axios
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 call-bind-apply-helpers
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 chalk
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 cliui
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 color-convert
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 color-name
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 combined-stream
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 concurrently
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 delayed-stream
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 detect-libc
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 dunder-proto
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 emoji-regex
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 enhanced-resolve
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 es-define-property
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 es-errors
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 es-object-atoms
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 es-set-tostringtag
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 esbuild
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 escalade
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 fdir
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 follow-redirects
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 form-data
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 function-bind
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 get-caller-file
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 get-intrinsic
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 get-proto
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 gopd
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 graceful-fs
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 has-flag
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 has-symbols
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 has-tostringtag
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 hasown
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 is-fullwidth-code-point
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 jiti
drwxr-xr-x 5 akase244 akase244 4096 2月 23 13:35 laravel-vite-plugin
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 lightningcss
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 lightningcss-linux-x64-musl
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 magic-string
drwxr-xr-x 5 akase244 akase244 4096 2月 23 13:35 math-intrinsics
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 mime-db
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 mime-types
drwxr-xr-x 6 akase244 akase244 4096 2月 23 13:35 nanoid
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 picocolors
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 picomatch
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 postcss
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 proxy-from-env
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 require-directory
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 rollup
drwxr-xr-x 9 akase244 akase244 4096 2月 23 13:35 rxjs
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 shell-quote
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 source-map-js
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 string-width
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 strip-ansi
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 supports-color
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 tailwindcss
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 tapable
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 tinyglobby
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 tree-kill
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 tslib
drwxr-xr-x 6 akase244 akase244 4096 2月 23 13:35 vite
drwxr-xr-x 4 akase244 akase244 4096 2月 23 13:35 vite-plugin-full-reload
drwxr-xr-x 2 akase244 akase244 4096 2月 23 13:35 wrap-ansi
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 y18n
drwxr-xr-x 6 akase244 akase244 4096 2月 23 13:35 yargs
drwxr-xr-x 3 akase244 akase244 4096 2月 23 13:35 yargs-parser
それでは公式のインストールガイドに従って、 composer run dev を実行して Laravel のアプリケーションを起動してみます。
Laravel のアプリケーションを composer run dev のように実行すると 127.0.0.1:8000 でポートを開放するため、コンテナ環境で実行するとローカルPCからアクセスできません。
これに対応するため、以下のように composer.json の php artisan serve に --host と --port のオプションを追加します。
※これによりローカル環境で直接 composer run dev を実行すると 0.0.0.0:8000 で開放することになるので、取り扱いにはご注意ください。
$ cp composer.json composer.json.orig.$(date +'%Y%m%d%H%M%S')
$ vim composer.json
$ diff composer.json composer.json.orig.20260223152708
48c48
< "npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve --host=0.0.0.0 --port=8000\" \"php artisan queue:listen --tries=1 --timeout=0\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite --kill-others"
---
> "npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1 --timeout=0\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite --kill-others"
同様に、 Vite が 127.0.0.1:5173 でポートを開放するため、コンテナ環境で実行するとローカルPCからアクセスできません。
これに対応するため、以下のように vite.config.js の export default defineConfig 内の server に以下の指定を追加します。
※これによりローカル環境で直接 composer run dev を実行すると 0.0.0.0:5173 で開放することになるので、取り扱いにはご注意ください。
$ cp vite.config.js vite.config.js.orig.$(date +'%Y%m%d%H%M%S')
$ vim vite.config.js
$ diff vite.config.js vite.config.js.orig.20260223152840
14,19d13
< host: '0.0.0.0',
< port: 5173,
< strictPort: true,
< hmr: {
< host: 'localhost',
< },
起動時に実行される php artisan pail により pcntl が必要となりますので、 Composer の Docker イメージではなく、 PHP の Docker Official Image を利用します。
$ docker container run \
--rm \
-v $(pwd):/app \
-w /app \
-p 127.0.0.1:8000:8000 \
-p 127.0.0.1:5173:5173 \
-it php:8.5-cli-alpine \
sh -c "
apk add --no-cache nodejs npm \
&& docker-php-ext-install pcntl \
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
&& composer run dev
"
Laravel アプリケーションの起動の処理に成功すると、以下のようなログが表示されます。
・
・
省略
・
・
> npx concurrently -c "#93c5fd,#c4b5fd,#fb7185,#fdba74" "php artisan serve --host=0.0.0.0 --port=8000" "php artisan queue:listen --tries=1 --timeout=0" "php artisan pail --timeout=0" "npm run dev" --names=server,queue,logs,vite --kill-others
[queue]
[queue] INFO Processing jobs from the [default] queue.
[queue]
[vite]
[vite] > dev
[vite] > vite
[vite]
[logs]
[logs] INFO Tailing application logs. Press Ctrl+C to exit
[logs] Use -v|-vv to show more details
[vite]
[vite] VITE v7.3.1 ready in 394 ms
[vite]
[vite] ➜ Local: http://localhost:5173/
[vite] ➜ Network: http://172.17.0.2:5173/
[server]
[server] INFO Server running on [http://0.0.0.0:8000].
[server]
[server] Press Ctrl+C to stop the server
[server]
[vite]
[vite] LARAVEL v12.52.0 plugin v2.1.0
[vite]
[vite] ➜ APP_URL: http://localhost:8000
ローカル環境で意図通りにポート番号が開放されていることを確認します。
$ ss -lnpt |grep -E '(:8000|:5173)'
LISTEN 0 4096 127.0.0.1:8000 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:5173 0.0.0.0:*
ブラウザで http://localhost:8000 にアクセスすると Laravel のデフォルト画面が表示されます。
同様にブラウザで http://localhost:5173/ にアクセスすると Vite のデフォルト画面が表示されます。
Laravel Sail のインストール
Laravel Sail のドキュメントに従って、先程作成した Laravel アプリケーションに対して composer require laravel/sail --dev を実行して、 Laravel Sail をインストールします。
$ cd /PATH_TO/my-laravel-sail
$ docker container run \
--rm \
-u $(id -u):$(id -g) \
-v $(pwd):/app \
-it composer:latest \
composer require laravel/sail --dev
Laravel Sail のインストール工程が進むと、以下のようなメッセージが表示されて完了します。
・
・
省略
・
・
INFO Discovering packages.
laravel/pail ............................................................. DONE
laravel/sail ............................................................. DONE
laravel/tinker ........................................................... DONE
nesbot/carbon ............................................................ DONE
nunomaduro/collision ..................................................... DONE
nunomaduro/termwind ...................................................... DONE
81 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
INFO No publishable resources for tag [laravel-assets].
No security vulnerability advisories found.
Using version ^1.53 for laravel/sail
.env のバックアップを取得します。
$ cp .env .env.orig.$(date +'%Y%m%d%H%M%S')
$ ls -l .env.orig.20260223153140
-rw-r--r-- 1 akase244 akase244 1142 2月 23 15:31 .env.orig.20260223153140
次に php artisan sail:install を実行して、 compose.yaml の作成や .env の更新を行います。
$ docker container run \
--rm \
-u $(id -u):$(id -g) \
-v $(pwd):/app \
-it composer:latest \
php artisan sail:install
データベースの選択肢が表示されるので mysql を選択します。
※なぜ SQLite の選択肢が無いのか。。。
┌ Which services would you like to install? ───────────────────┐
│ › ◼ mysql ┃ │
│ ◻ pgsql │ │
│ ◻ mariadb │ │
│ ◻ mongodb │ │
│ ◻ redis │ │
└────────────────────────────────────────────────── 1 selected ┘
Use the space bar to select options.
以下のように表示されたら php artisan sail:install の実行は完了です。
┌ Which services would you like to install? ───────────────────┐
│ mysql │
└──────────────────────────────────────────────────────────────┘
INFO Sail scaffolding installed successfully. You may run your Docker containers using Sail's "up" command.
➜ ./vendor/bin/sail up
WARN A database service was installed. Run "artisan migrate" to prepare your database:
➜ ./vendor/bin/sail artisan migrate
php artisan sail:install の実行により .env が更新されているはずなので差分を確認すると、データベースの接続先が SQLite から MySQL に変更されています。
$ diff .env .env.orig.20260223153140
14c14
< PHP_CLI_SERVER_WORKERS=4
---
> # PHP_CLI_SERVER_WORKERS=4
23,28c23,28
< DB_CONNECTION=mysql
< DB_HOST=mysql
< DB_PORT=3306
< DB_DATABASE=laravel
< DB_USERNAME=sail
< DB_PASSWORD=password
---
> DB_CONNECTION=sqlite
> # DB_HOST=127.0.0.1
> # DB_PORT=3306
> # DB_DATABASE=laravel
> # DB_USERNAME=root
> # DB_PASSWORD=
作成された compose.yaml を参照すると ports に以下のような指定があります。
$ cat compose.yaml
services:
laravel.test:
・
・
ports:
- '${APP_PORT:-80}:80'
- '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
・
・
mysql:
image: 'mysql:8.4'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
・
・
compose.yaml のバックアップファイルを作成して、以下のように修正します。
$ cp compose.yaml compose.yaml.orig.$(date +'%Y%m%d%H%M%S')
$ vim compose.yaml
$ diff compose.yaml compose.yaml.orig.20260223155130
12,13c12,13
< - '127.0.0.1:${APP_PORT:-80}:80'
< - '127.0.0.1:${VITE_PORT:-5173}:${VITE_PORT:-5173}'
---
> - '${APP_PORT:-80}:80'
> - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
29c29
< - '127.0.0.1:${FORWARD_DB_PORT:-3306}:3306'
---
> - '${FORWARD_DB_PORT:-3306}:3306'
Laravel Sail を起動します。
$ ./vendor/bin/sail up
ローカル環境で意図通りにポート番号が開放されていることを確認します。
$ ss -lnpt |grep -E '(:80|:5173|:3306)'
LISTEN 0 4096 127.0.0.1:3306 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:80 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:5173 0.0.0.0:*
Laravel Sail を起動した状態でデータベースのマイグレーションを実行してみると、すべて適用済みのようです。
$ ./vendor/bin/sail artisan migrate
INFO Nothing to migrate.
マイグレーションのファイルを確認します。全部で3ファイル存在するようです。
$ ls -l database/migrations/
合計 12
-rw-r--r-- 1 akase244 akase244 1473 1月 20 02:57 0001_01_01_000000_create_users_table.php
-rw-r--r-- 1 akase244 akase244 867 1月 20 02:57 0001_01_01_000001_create_cache_table.php
-rw-r--r-- 1 akase244 akase244 1812 1月 20 02:57 0001_01_01_000002_create_jobs_table.php
マイグレーションが本当に適用済みなのかを Docker コンテナ内に直接入って調べるため、データベースの接続情報を確認します。
$ grep DB_ .env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=sail
DB_PASSWORD=password
起動中の MySQL の Docker コンテナのIDを調べます。
$ docker container ls |grep mysql
d18b30780d8d mysql:8.4 "docker-entrypoint.s…" 16 minutes ago Up 10 minutes (healthy) 127.0.0.1:3306->3306/tcp, 33060/tcp my-laravel-sail-mysql-1
Docker コンテナに入ります。
$ docker exec -it d18b30780d8d bash
bash-5.1#
事前に調べておいた接続情報で MySQL に接続します。
bash-5.1# mysql -u sail -p laravel
Enter password:
・
・
省略
・
・
mysql>
laravel データベースのテーブル一覧を確認すると、 MySQL 内に正常に作成されていることがわかります。
mysql> show tables;
+-----------------------+
| Tables_in_laravel |
+-----------------------+
| cache |
| cache_locks |
| failed_jobs |
| job_batches |
| jobs |
| migrations |
| password_reset_tokens |
| sessions |
| users |
+-----------------------+
9 rows in set (0.00 sec)
migrations を参照して、マイグレーションの実行状況を確認してみると、 batch 列の値が 1 になっているので、すべて実行済みのようです。
mysql> select * from migrations;
+----+--------------------------------------+-------+
| id | migration | batch |
+----+--------------------------------------+-------+
| 1 | 0001_01_01_000000_create_users_table | 1 |
| 2 | 0001_01_01_000001_create_cache_table | 1 |
| 3 | 0001_01_01_000002_create_jobs_table | 1 |
+----+--------------------------------------+-------+
3 rows in set (0.00 sec)
ブラウザで http://localhost にアクセスすると Laravel のデフォルト画面が表示されます。
※Laravel Sail ではポート番号が80に変更になっているため、「:8000」の指定は不要です。
Sail-SSL のインストール
Sail-SSL を利用することでHTTPS接続が簡単に行えますので、これを導入します。
Laravel Sail を起動します。
$ cd /PATH_TO/my-laravel-sail
$ ./vendor/bin/sail up -d
sail composer コマンドで ryoluo/sail-ssl を導入します。
$ ./vendor/bin/sail composer require ryoluo/sail-ssl --dev
以下のように表示されれば導入完了です。
・
・
省略
・
・
INFO Discovering packages.
laravel/pail ......................................................... DONE
laravel/sail ......................................................... DONE
laravel/tinker ....................................................... DONE
nesbot/carbon ........................................................ DONE
nunomaduro/collision ................................................. DONE
nunomaduro/termwind .................................................. DONE
ryoluo/sail-ssl ...................................................... DONE
81 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
INFO No publishable resources for tag [laravel-assets].
No security vulnerability advisories found.
Using version ^1.4 for ryoluo/sail-ssl
compose.yaml のバックアップを取得します。
$ cp compose.yaml compose.yaml.orig.$(date +'%Y%m%d%H%M%S')
$ ls -l compose.yaml.orig.20260223165024
-rw-r--r-- 1 akase244 akase244 1780 2月 23 16:50 compose.yaml.orig.20260223165024
sail artisan コマンドで sail-ssl:install を実行すると、 docker-compose.yml が存在しないため処理が終了してしまいました。
$ ./vendor/bin/sail artisan sail-ssl:install
ErrorException
file_get_contents(/var/www/html/docker-compose.yml): Failed to open stream: No such file or directory
at vendor/ryoluo/sail-ssl/src/Console/InstallCommand.php:29
25▕ * @return void
26▕ */
27▕ public function handle()
28▕ {
➜ 29▕ $dockerCompose = file_get_contents($this->laravel->basePath('docker-compose.yml'));
30▕ if (str_contains($dockerCompose, 'nginx:')) {
31▕ $this->info('Nginx container is already installed. Do nothing.');
32▕ return;
33▕ }
+14 vendor frames
15 artisan:16
Illuminate\Foundation\Application::handleCommand()
Laravel Sail では docker-compose.yml ではなく compose.yaml を作成する構成になっています。
なので、 Sail-SSL が現状の構成に追いついてない部分があるようです。
以下を参照する限り、うまいこと動くような気がしなくもないですが。。。
仕方がないので、 compose.yaml を docker-compose.yml にコピーして再度 sail-ssl:install を実行してみます。
実行時のメッセージでは my-laravel-sail ディレクトリ配下の compose.yaml を利用しているように見えます。
$ cp compose.yaml docker-compose.yml
$ ./vendor/bin/sail artisan sail-ssl:install
WARN[0000] Found multiple config files with supported names: /home/akase244/repos/my-laravel-sail/compose.yaml, /home/akase244/repos/my-laravel-sail/docker-compose.yml
WARN[0000] Using /home/akase244/repos/my-laravel-sail/compose.yaml
WARN[0000] Found multiple config files with supported names: /home/akase244/repos/my-laravel-sail/compose.yaml, /home/akase244/repos/my-laravel-sail/docker-compose.yml
WARN[0000] Using /home/akase244/repos/my-laravel-sail/compose.yaml
WARN[0000] Found multiple config files with supported names: /home/akase244/repos/my-laravel-sail/compose.yaml, /home/akase244/repos/my-laravel-sail/docker-compose.yml
WARN[0000] Using /home/akase244/repos/my-laravel-sail/compose.yaml
Nginx container successfully installed in Docker Compose.
事前に取得してた compose.yaml のバックアップと比較してみると、差分は発生していません。
$ diff compose.yaml compose.yaml.orig.20260223165024
(何も表示されない)
どうやら、 docker-compose.yml の方に Nginx の設定が追加されているようです。
$ diff docker-compose.yml compose.yaml.orig.20260223165024
2,20d1
< nginx:
< image: 'nginx:latest'
< ports:
< - '${HTTP_PORT:-8000}:80'
< - '${SSL_PORT:-443}:443'
< environment:
< - SSL_PORT=${SSL_PORT:-443}
< - APP_SERVICE=${APP_SERVICE:-laravel.test}
< - SERVER_NAME=${SERVER_NAME:-localhost}
< - SSL_DOMAIN=${SSL_DOMAIN:-localhost}
< - SSL_ALT_NAME=${SSL_ALT_NAME:-DNS:localhost}
< volumes:
< - 'sail-nginx:/etc/nginx/certs'
< - './vendor/ryoluo/sail-ssl/nginx/templates:/etc/nginx/templates'
< - './vendor/ryoluo/sail-ssl/nginx/generate-ssl-cert.sh:/docker-entrypoint.d/99-generate-ssl-cert.sh'
< depends_on:
< - ${APP_SERVICE:-laravel.test}
< networks:
< - sail
74,75d54
< sail-nginx:
< driver: local
なので、 docker-compose.yml の内容を compose.yaml に反映します。
$ cp docker-compose.yml compose.yaml
Nginx が 0.0.0.0 で起動するようになっているので修正します。
$ cp compose.yaml compose.yaml.orig.$(date +'%Y%m%d%H%M%S')
$ vim compose.yaml
$ diff compose.yaml compose.yaml.orig.20260223171425
5,6c5,6
< - '127.0.0.1:${HTTP_PORT:-8000}:80'
< - '127.0.0.1:${SSL_PORT:-443}:443'
---
> - '${HTTP_PORT:-8000}:80'
> - '${SSL_PORT:-443}:443'
Sail-SSL のドキュメントに従って、 Laravel Sail を停止して、起動します。
$ ./vendor/bin/sail down
$ ./vendor/bin/sail up
ブラウザで http://localhost にアクセスすると Laravel のデフォルト画面が表示されます。
ブラウザで https://localhost にアクセスすると証明書の警告が表示されます。
「詳細設定」から「localhost にアクセスする(安全ではありません)」をクリックします。
HTTPS接続で Laravel のデフォルト画面が表示されます。
Sail-SSL のドキュメントに従って、 Nginx のコンテナからルート証明書を取り出そうとすると失敗しました。
$ ./vendor/bin/sail cp nginx:/etc/nginx/certs/root-ca.crt .
WARN[0000] Found multiple config files with supported names: /home/akase244/repos/my-laravel-sail/compose.yaml, /home/akase244/repos/my-laravel-sail/docker-compose.yml
WARN[0000] Using /home/akase244/repos/my-laravel-sail/compose.yaml
WARN[0000] Found multiple config files with supported names: /home/akase244/repos/my-laravel-sail/compose.yaml, /home/akase244/repos/my-laravel-sail/docker-compose.yml
WARN[0000] Using /home/akase244/repos/my-laravel-sail/compose.yaml
[+] copy 0/1
⠋ my-laravel-sail-nginx-1 Copying my-laravel-sail-nginx-1:/etc/nginx/certs/root-ca.crt to . 0.0s
Error response from daemon: Could not find the file /etc/nginx/certs/root-ca.crt in container b4ea155c739d415c8bd220f55110d55350c9485c80684f18d01cf453b018b9de
起動中の Nginx の Docker コンテナのIDを調べます。
$ docker container ls |grep nginx
b4ea155c739d nginx:latest "/docker-entrypoint.…" 8 minutes ago Up 8 minutes 127.0.0.1:443->443/tcp, 127.0.0.1:8000->80/tcp my-laravel-sail-nginx-1
Docker コンテナに入ります。
$ docker exec -it b4ea155c739d bash
root@b4ea155c739d:/#
/etc/nginx/certs/ 配下にはサーバー証明書しかなさそうです。
root@b4ea155c739d:/# ls -l /etc/nginx/certs/
total 8
-rw------- 1 root root 1704 Feb 23 08:11 server.key
-rw-r--r-- 1 root root 1143 Feb 23 08:11 server.pem
Sail-SSL のソースコードを参照するとたしかに root-ca.crt で作成されてそうに見えるんですが。。。
後処理で削除されていませんし、通常であれば root-ca.crt を取り出す形が正しいかと思います。
server.pem がルート証明書としても利用可能なサーバー証明書なのか確認してみたところ、「CA:TRUE」となっているため、これは「CA証明書(ルート証明書)」兼「サーバー証明書」の形で発行されているようです。
root@b4ea155c739d:/# openssl x509 -in /etc/nginx/certs/server.pem -noout -text | grep -A 1 "Basic Constraints"
X509v3 Basic Constraints: critical
CA:TRUE
しかし、Sail-SSL のソースコードを参照すると CA:FALSE が指定されています。謎。。。
まぁ、ということで、 /etc/nginx/certs/server.pem を取り出します。
$ ./vendor/bin/sail cp nginx:/etc/nginx/certs/server.pem .
WARN[0000] Found multiple config files with supported names: /home/akase244/repos/my-laravel-sail/compose.yaml, /home/akase244/repos/my-laravel-sail/docker-compose.yml
WARN[0000] Using /home/akase244/repos/my-laravel-sail/compose.yaml
WARN[0000] Found multiple config files with supported names: /home/akase244/repos/my-laravel-sail/compose.yaml, /home/akase244/repos/my-laravel-sail/docker-compose.yml
WARN[0000] Using /home/akase244/repos/my-laravel-sail/compose.yaml
[+] copy 1/1
✔ my-laravel-sail-nginx-1 Copied my-laravel-sail-nginx-1:/etc/nginx/certs/server.pem to . 0.0s
$ ls -l server.pem
-rw-r--r-- 1 akase244 akase244 1143 2月 23 17:11 server.pem
Chrome で「 chrome://settings/certificates 」を入力して「証明書マネージャ」を開きます。
「カスタム」→「自分でインストール」を選択し、「信頼できる証明書」に Nginx のコンテナから取り出したルート証明書をインポートします。
ブラウザで https://localhost にアクセスすると証明書の警告は表示されずにアクセスすることができました。
※証明書インポート後も警告が消えない場合は、一旦開いてるブラウザをすべて閉じてからアクセスしなおすと解消するはずです。(多分)
いかがだったでしょうか。
Docker コンテナを駆使することで、ローカル環境に追加でコマンド類をインストールすることなく Laravel Sail の環境を構築できることがわかったのではないでしょうか。
参考記事









