基于 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

实例教程


Vote Vote Cancel Collect Collect Cancel

<< 上一篇: 基于 Laravel Passport 提供 OAuth2 认证解决方案

>> 下一篇: 基于 Laravel Sanctum 提供 SPA 认证解决方案