基于 Laravel Sail 搭建 Docker 本地集成开发环境
Laravel Sail 是一个与 Laravel 默认 Docker 开发环境进行交互的轻量级命令行界面。Sail 为使用 PHP、MySQL、Redis 构建 Laravel 应用提供了很好的起点,不需要有任何 Docker 经验就可以轻松上手。
Sail 的核心是在 Laravel 项目根目录下提供 docker-compose.yml
文件(Docker Compose 编排配置文件)以及一个 sail
脚本文件,该脚本文件提供了与 docker-compose.yml
中定义的 Docker 容器进行交互的 CLI 方法。
Laravel Sail 目前支持 macOS、Linux 和 Windows(基于 WSL2)操作系统。
与非官方的 Docker 集成开发环境相比(比如 Laradock、Vessel、Lando 等),Sail 更加轻量级,与 Laravel 项目兼容性更好,对新手更加友好,对于一些演示项目、或者小项目开发,推荐使用 Laravel Sail。
安装 & 设置
Laravel Sail 会随着新项目一起自动安装,所以开箱即用的,关于如何创建新的 Laravel 应用,可以参考前面的安装配置文档。
在已存在的项目中使用
如果你想要在已存在的 Laravel 项目中使用 Sail,可以通过 Composer 安装对应的扩展包:
composer require laravel/sail --dev
Sail 安装完成后,需要运行 Artisan 命令 sail:install
将 Sail 的 Docker Compose 编排文件 docker-compose.yml
发布到项目根目录下:
php artisan sail:install
最后,通过如下命令启动 Sail 即可:
./vendor/bin/sail up
配置 Bash 别名
默认情况下,需要通过 vendor/bin/sail
调用 Sail 命令:
./vendor/bin/sail up
如果你觉得每次重复输入 ./vendor/bin/sail
很麻烦,可以为其设置一个 Bash 别名进行简化:
alias sail='bash vendor/bin/sail'
配置好这个 Bash 别名后,就可以直接使用 sail
执行 Sail 命令了。后续教程我们将基于这个别名调用 Sail 命令:
sail up
启动 & 停止 Sail
Laravel Sail 的 docker-compose.yml
文件编排了多个 Docker 容器,它们可以一起协同工作从而帮助你构建起 Laravel 应用的运行环境。每个容器都作为一个条目配置在 docker-compose.yml
文件的 services
配置项中,其中的 laravel.test
容器是主应用容器,用于部署项目代码对外提供服务。
如果你之前有过 Docker Compose 或者 Laradock 的使用经验,这些很好理解,
laravel.test
类似 Laradock 的workspace
容器,只是现在每个容器只服务一个应用。
启动 Sail 之前,需要确保本地计算机上没有启动其他 Web 服务器或者数据库(否则会出现端口冲突),你可以通过执行 up
命令启动 docker-compose.yml
文件中定义的所有 Docker 容器:
sail up
如果是在后台启动这些 Docker 容器,可以追加一个 -d
选项:
sail up -d
应用容器启动之后,就可以在浏览器中通过 http://localhost
访问该项目了。
要停止所有容器,只需要通过 Ctrl + C 终止上述终端命令运行即可。如果是后台运行,则可以通过 down
命令停止:
sail down
注:显然,Sail 底层还是调用
docker-compose
命令管理容器服务,基本命令名称也一致。
执行命令
使用 Laravel Sail 的时候,你的应用是在 Docker 容器中运行的,而容器环境和本地宿主机是互相隔离的。不过,Sail 提供了非常方便的方式,让你可以直接在宿主机环境命令行与应用进行交互(比如运行 PHP 命令、Artisan 命令、Composer 命令以及 NPM 命令),而无需登录到 Docker 容器。
之前的 Laravel 文档都是基于非 Docker 环境的本地宿主机,所以你看到的都是直接调用这些 PHP 命令、Artisan 命令、Composer 命令以及 NPM 命令,这没什么问题,但是如果基于 Sail 作为本地开发环境,其底层使用的是 Docker 容器,对应的操作系统和目录路径和本地宿主机都是不一样的,好在不同于一般的通用 Docker 本地开发环境,Sail 很好地兼容了这个问题。
接下来,我们就来看看 Sail 是如何优雅地解决这个问题的。
执行 PHP 命令
对于直接通过 php
命令运行的 PHP 脚本,只需要在 php
前面加上 sail
前缀即可:
sail php --version
sail php script.php
执行 Composer 命令
对于通过 composer
命令运行的 Composer 命令,Laravel Sail 应用容器内置了对 Composer 2.x 的支持,所以和 php
命令一样,只需要在 composer
前面加上 sail
即表示在 Sail 中运行这个命令:
sail composer require laravel/sanctum
执行 Artisan 命令
对于 Laravel Artisan 命令,只需将之前的 php
改为 sail
即可:
# 本地运行 Artisan 命令...
php artisan queue:work
# 在 Sail 中运行 Artisan 命令...
sail artisan queue:work
执行 Node/NPM 命令
和 php
命令一样,对于 Node/NPM 命令,只需在 node
/npm
命令之前加上 sail
以示区分即可:
sail node --version
sail npm run prod
与数据库交互
MySQL
你可能已经注意到,docker-compose.yml
文件中包含了一个 MySQL 容器条目,该容器使用了 Docker 数据卷以便存储在容器数据库中的数据可以持久化,即便容器关闭或重启,数据依然不会被销毁。此外,当 MySQL 容器启动时,会基于 Laravel 项目环境变量 DB_DATABASE
中配置的数据库建立与数据库容器的连接。
启动 MySQL 容器后,就可以在 .env
中配置 Laravel 项目的环境变量 DB_HOST
值为 mysql
建立与数据库容器的连接了。
如果想要在本地宿主机连接到 MySQL 数据库(时刻牢记使用 Sail 启动应用后,应用是运行在 Docker 容器而非本地宿主机的,上面配置的 mysql
也是 Docker 内部基于容器名建立连接),可以使用图形化数据管理工具,比如 TablePlus。默认情况下,可以直接通过 localhost
和 3306 端口连接到 MySQL 数据库容器。
Redis
docker-compose.yml
中还包含了 Redis 容器条目。该容器也使用了 Docker 数据卷,对 Redis 数据进行持久化存储,从而确保即便 Redis 容器停止和重启,数据也不会被销毁。在应用容器启动后,会基于 .env
中配置的 REDIS_HOST
环境变量匹配的 redis
连接与 Redis 容器建立连接。
如果想要在本地宿主机连接到 Redis 数据库,可以使用图形化数据库管理工具,例如 TablePlus。默认情况下,Redis 数据库容器可以通过 localhost
和 6379 端口访问。
运行测试
Laravel 开箱提供了非常出色的测试支持,你可以使用 Sail 提供的测试命令 test
在宿主机执行运行在 Docker 容器中的项目代码功能和单元测试:
sail test
sail test --group orders
当然,你也可以通过 Artisan 命令进行测试:
sail artisan test
两者的效果是等价的。
Laravel Dusk
Laravel Dusk 提供了非常优雅的、易于使用的浏览器自动化测试 API。使用 Sail 的话,基于 Dusk 进行浏览器测试更加方便了,不需要在本地宿主机安装 Selenium 或者任何其他工具,在 docker-compose.yml
文件中取消 Selenium 服务注释:
selenium:
image: 'selenium/standalone-chrome'
volumes:
- '/dev/shm:/dev/shm'
networks:
- sail
然后确保 docker-compose.yml
文件中的 laravel.test
服务 depends_on
配置项中包含 selenium
:
depends_on:
- mysql
- redis
- selenium
就可以通过如下 Sail dusk
命令运行 Dusk 测试用例了:
sail dusk
预览邮件
Laravel Sail 默认的 docker-compose.yml
文件还包含了一个服务条目 MailHog,该服务用于在本地开发期间拦截应用发送的所有邮件并提供一个 Web 界面在浏览器中预览这些邮件信息,方便测试和调试。MailHog 默认的 SMTP 端口号是 1025
:
MAIL_PORT=1025
当 Sail 运行时,你可以通过 http://localhost:8025
访问 MailHog Web 界面。
容器 CLI
有时候,你可能想要在应用容器中开启一个 Bash 会话,这可以通过调用 Sail 提供的 shell
命令连接到应用 Docker 容器来实现:
sail shell
这样一来,你就可以和容器中所有文件和已安装服务进行交互了。
你甚至还可以通过 tinker
命令开启一个新的 Laravel Tinker 会话:
sail tinker
PHP 版本
Sail 目前支持 PHP 8.0 和 PHP 7.4 版本,要切换 PHP 版本,需要更新 docker-compose.yml
中的 laravel.test
容器 build
定义:
# PHP 8.0
context: ./vendor/laravel/sail/runtimes/8.0
# PHP 7.4
context: ./vendor/laravel/sail/runtimes/7.4
此外,如果你想要修改应用容器使用的 PHP 版本镜像,需要更新 docker-compose.yml
中对应的 image
名称:
image: sail-8.0/app
更新过 docker-compose.yml
文件后,需要重构容器镜像让修改生效:
sail build --no-cache
sail up
分享你的站点
有时候你可能想要将本地站点公开,以便让同事可以预览,或者测试外部接口调用。要公开你的站点,可以使用 share
命令,运行该命令后,会获取到一个随机的用于访问站点的 laravel-sail.site
URL:
sail share
如果你想要设置共享站点的子域名,可以在执行 share
命令时提供一个 subdomain
选项:
sail share --subdomain=my-sail-site
share
基于 Expose 驱动,这是一个由 BeyondCode 开源的基于 PHP 实现的隧道服务。
Sail 自定义
由于 Sail 本质上是基于 Docker 容器的,所以你可以对其所有行为特性进行自定义。要自定义 Sail 的话,需要先通过 sail:publish
命令发布 Sail 的 Dockerfile:
sail artisan sail:publish
运行上述命令后,会将 Sail 自带的所有 Dockerfile 和其他配置文件发布到项目根目录下的 docker
子目录中,你可以通过修改这些文件自定义 Sail,修改完成后,需要使用 build
命令重建应用容器让所有更改生效:
sail build --no-cache
4 Comments
这跟我想到一起去了,定义一套统一的基础环境 https://www.laraveladmin.cn
请问是任意一个laravel版本都可以使用么,还是只有8以后才可以。
8以后,其他版本你用 laradock 也是一样的,通用性更强:https://laravelacademy.org/post/9608
sail 可以支持多个项目吗