【Laravel】公式のDocker環境Laravel Sailを起動するまで

Laravel公式のDocker環境``Laravel　　Sail``を起動するまでの流れをまとめました。起動時によくあるエラーの解決方法も説明しています。

# ゴール
Laravel Sailを利用してLaravelのデフォルト画面を表示する。
![スクリーンショット 2022-03-07 23.29.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654760/d0179e0c-a2bb-946c-f4b5-9c41de6ebaed.png)

# 準備
Docker Desktopを起動してください。
インストールの方法は[こちら](https://docs.docker.jp/desktop/index.html#desktop-download-and-install)から。

# 検証環境
- macOS Catarina 10.15.7
- Docker Desktop 4.6.0

# インストール

[公式サイト](https://laravel.com/docs/9.x/installation#your-first-laravel-project)に記載されているコマンドをそのまま実行します。
ディレクトリ``example-app``が作成され、その中にファイルが展開されます。
```bash
% curl -s "https://laravel.build/example-app" | bash
```

最後にパスワードを求められるので、端末のパスワードを入力します。
```bash
Please provide your password so we can make some final adjustments to your application's permissions.

Password:
```

こちらのメッセージが表示されたらインストール完了です。
```bash
Thank you! We hope you build something incredible. Dive in with: cd example-app && ./vendor/bin/sail up
```

## インストール直後のソース

インストール直後の``example-app``の内容です。
```bash
% cd example-app
% tree -L 1
.
├── README.md
├── app
├── artisan
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── docker-compose.yml
├── lang
├── package.json
├── phpunit.xml
├── public
├── resources
├── routes
├── storage
├── tests
├── vendor
└── webpack.mix.js

11 directories, 8 files
```

# イメージ構築・コンテナ起動
完了メッセージの通り、``example-app``へ移動し``./vendor/bin/sail up``を実行します。

```bash
Thank you! We hope you build something incredible. Dive in with: cd example-app && ./vendor/bin/sail up
```

Dockerを使った経験がある方は見覚えがあるかと思いますが、動作は``docker-compose up``と同じです。``dオプション``をつけるとバックグラウンドでコンテナを実行できます。
```bash
% cd example-app
% ./vendor/bin/sail up -d
```

# デフォルト画面を表示
ブラウザで[localhost](http://localhost/)へアクセスし、Laravelのデフォルト画面が表示できればOKです。![スクリーンショット 2022-03-07 23.29.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654760/4aa79f1e-ff66-a663-0037-6ae9b12f74ed.png)

# エラーが発生したら
## ポートが既に使われている
Sailの起動に必要なポートが既に使用されている場合にエラーが発生します。

```bash
# 80番ポートが既に使用されている
Error response from daemon: driver failed programming external connectivity on endpoint example-app-laravel.test-1 (0b19dc86c5561d920605fb84f36e99016d7cfde3baf771e38fba4127a902cee8): Bind for 0.0.0.0:80 failed: port is already allocated
```

```bash
# 3306番ポートが既に使用されている
Error response from daemon: Ports are not available: listen tcp 0.0.0.0:3306: bind: address already in use
```

2種類の解決方法を紹介します。
### ポートを使用している他プロセスを終了する
Sailの起動に必要なポートを空けるため、他のプロセスを終了します。

ポートを使用しているプロセスを確認します。
``lsofコマンド``でポート番号からプロセスの内容を表示できます。

```bash
# 80番ポートを使用中のプロセスを確認
% lsof -i:80
```

終了して問題が無ければ、プロセスを終了します。

もしくは、他のコンテナでポートが使用されているかもしれません。``docker ps``で起動中のコンテナを表示できます。dockerのプロセスはlsofでも表示できますが、コンテナに絞って確認する場合はdocker psの方が見やすいです。

```bash
% docker ps
```

他のコンテナでポートが使用されている場合は、そのコンテナを停止します。

```bash
% docker-compose down
```

### Sailの使用ポートを変更する
Sailで使用するデフォルトのポートを80番から8080番へ変更する方法です。ポートは``example-app/docker-compose.yml``で設定されています。

80番ポートは``laravel.test``という名前のコンテナで使用されています。

```docker-compose.yml
# For more information: https://laravel.com/docs/sail
version: '3'
services:
    laravel.test:
        build:
            context: ./vendor/laravel/sail/runtimes/8.1
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: sail-8.1/app
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'                      # ここで80番ポートを指定
```

ポートの設定部分を簡単に説明します。
- ローカルの80番ポートをコンテナの80番ポートへ紐付けている（ポートフォワード）
- ``${APP_PORT:-80}``は、環境変数``APP_PORT``が存在しない場合は``80``に置き換えるという意味
```docker-compose.yml
- '${APP_PORT:-80}:80'  
```

ローカルのポート指定を変更しますが、方法は2種類あります。
どちらでも動きますが``APP_PORT``を定義した方が設定が明示的で良いと思います。
- ``.env``にAPP_PORTを定義する
```.env
APP_PORT=8080
```

- ``${APP_PORT:-80}``のデフォルト値を別の値に変更する
```docker-compose.yml
- '${APP_PORT:-8080}:80'  
```

### コンテナの再起動
解決後、コンテナを再起動します。

```bash
# コンテナを停止
% ./vendor/bin/sail down
# コンテナを起動
% ./vendor/bin/sail up -d
```

## イメージが正しく構築されていない
イメージを再構築後、コンテナを再起動します。

コンテナを停止します。
```bash
% ./vendor/bin/sail down
```

イメージを再構築します。
```bash
% ./vendor/bin/sail build --no-cache
```

再度コンテナを起動します。
```bash
% ./vendor/bin/sail up -d
```

## Docker Desktopのバージョンが古い
Docker Desktopのバージョンが原因かもしれません。
最新バージョンでなければ更新して再度検証してみてください。

![スクリーンショット 2022-03-20 9.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654760/6bc76a06-1238-4815-4573-284fc625bf9c.png)

# まとめ
Laravel Sailのメリットは環境構築の容易さです。特にLaravelの学習に集中したい場合はとても便利なツールだと思います。

素敵なLaravelライフをお送りください。

# 参考記事
- [【Laravel Sail】 sail up コマンド実行時の Cannot start service … address already in use エラー](https://lotus-base.com/blog/35/)

# 採用PR
弊社で一緒に働く仲間を募集しています。
全てのオタクを幸せにしたい方、是非ご覧ください！

https://hrmos.co/pages/vivion/jobs/0000191