Laravel Sail – Ambiente Docker para quem nunca viu Docker (e para quem já viu também)

Tempo de leitura 6 minutos

O Laravel Sail é a forma oficial de iniciar um novo projeto Laravel, mas nada impede de você incluí-lo em seu projeto já existente, neste artigo quero falar sobre o que é o Laravel Sail e como ele já se tornou a melhor alternativa de ambiente para mim.

Não se esqueça de assinar a newsletter do blog para ficar por dentro das novidades.

O que é o Laravel Sail

O Laravel Sail é uma interface de linha de comando leve (assim como o artisan) e simples de usar. Seu foco é abstrair todo o uso do Docker para que seja mais simples durante o dia a dia.

Com o Sail é possível executar comandos do PHP, Composer, Node, Tinker , Artisan, rodar testes com o Laravel Dusk e até pré-visualizar e-mails com o MailHog.

Como é construído em Docker, você pode personalizar o ambiente com seu próprio Dockerfile, adicionando tudo o que você quiser, basta saber alterar arquivos do Docker (conhecimento que pode ser adquirido rápidamente, você pode começar por aqui).

Instalando o Docker

Se você não tem o Docker instalado saiba que ele é obrigatório (óbvio), porém é um tanto inviável eu descrever este passo a passo aqui neste momento, já que o processo pode mudar um pouco (muito) de ambiente para ambiente ou até ter várias formas se se fazer

Vou adiantar que Ainda bem que este é um processo MUITO BEM documentado pela internet a fora, recomendo “dar um Google” por “instalar o Docker no [sistema operacional] [versão]”.

Novo projeto Laravel com Laravel Sail

Para iniciar um novo projeto Laravel usando o Sail você só precisa executar um comando.

curl -s https://laravel.build/example-app | bash

Os usuários do Windows 10 (outras versões do Windows não estão contempladas na documentação oficial) vão precisar do Windows Subsystem for Linux 2 (WSL2) instalado, além do Windows Terminal.

Com isso você já irá instalar o Laravel com ambiente Docker e tudo o que tiver direito.

Adicionando o Laravel Sail a um projeto já existente

Para um projeto já existente, tudo o que você precisa é instalar um pacote com Composer e rodar um comando instalador.

Como mencionado assima, aém do Docker, usuários do Windows também irão precisar do Windows Subsystem for Linux 2 (WSL2) instalado, além do Windows Terminal.

composer require laravel/sail --dev
php artisan sail:install

Executando Laravel Sail

Para gerenciar seu ambiente Docker com o Sail é bem simples, basta acessar o ./vendor/bin/sail e em seguida o comando que você precisa executar.

Da até pra criar um alias no Linux utilizando o comando a seguir:

alias sail='bash vendor/bin/sail'

Daí é só acessar a raiz do projeto que possui uma instalação do Laravel Sail e executar:

sail [comando]

O comando para “subir” o ambiente Docker do Laravel Sail é:

sail up

Se você quiser rodar o servidor em background, basta apenas adicionar -d no comando e o terminal ficará liberado para você usar.

sail up -d

Finalmente, para parar o servidor você pode teclar ctrl+c ou, se estiver rodando em background, o comando sail down.

Para acessar o projeto no navegador, basta acessar http://localhost/.

Executando comandos com Laravel Sail (Artisan, PHP, Composer, Node e NPM)

Para executar comandos não muda quase nada, há não ser que todos devem ser precedidos pelo sail, com exceção do artisan que substitui o php.

Exemplos:

sail artisan queue:work
sail php --version
sail composer require laravel/sanctum
sail node --version
sail npm run prod

Um adendo importante é que o sail tem vários pacotes do Composer como dependência, então quando clonar um projeto, não esqueça de fazer a instalação dos pacotes ou Laravel Sail não irá funcionar, para rodar o composer install diretamente no Docker antes de ter um ambiente com Laravel Sail:

docker run --rm \
    -v $(pwd):/opt \
    -w /opt \
    laravelsail/php80-composer:latest \
    composer install

Bancos de dados (MySQL e Redis)

Como temos um ambiente completo, o MySQL e Redis não poderiam faltar e o acesso a isso é bem simplificado.

Quando o Laravel Sail inicia ele garante que um banco de dados com o nome setado na variável de ambiente (.env) DB_DATABASE exista.

Além disso você pode verificar se o DB_HOST contém o valor mysql (é o alias do container usado pelo Docker, como um IP ou domínio) para garantir a conexão.

Para acessar o banco de dados o recomendado é utilizar um cliente com interface gráfica, a documentação oficial sugere o TablePlus, eu gosto do MySQL Workbench e também tem o DBeaver.

Já o Redis, a regra é parecida com o MySQL, você vai precisar garantir que a variável de ambiente REDIS_HOST tem o valor redis.

Parace acessar o Redis, também é recomendado usar um aplicativo externo, a documentação recomenda novamente o TablePlus.

Rodando testes com Laravel Sail

A parte de testes é bem simples, basta trocar php artisan test por sail test.

sail test
sail test --group orders

Além dos testes com PHPUnit, podemos ter acesso ao Laravel Dusk de forma bem simplificada.

Vamos precisar ativar o “service” no docker-compose.yml, quem leu meu artigo anterior sobre Laravel com Docker sem o Laravel Sail sabe do que estou falando.

Para isso basta saber que o arquivo responsável por gerir o ambiente do Sail é o arquivo docker-compose.yml que é publicado quando você usa o comando php artisan sail:install na raiz do projeto.

Todo arquivo yml é organizado por identações, ou seja, o nó services possui o filho laravel.test e o build está dentro do laravel.test, aqui o arquivo na integra, você também pode encontrá-lo na raiz do seu projeto Laravel:

# For more information: https://laravel.com/docs/sail
version: '3'
services:
    laravel.test:
        build:
            context: ./vendor/laravel/sail/runtimes/8.0
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: sail-8.0/app
        ports:
            - '${APP_PORT:-80}:80'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
        volumes:
            - '.:/var/www/html'
        networks:
            - sail
        depends_on:
            - mysql
            # - pgsql
            - redis
            # - selenium
    # selenium:
    #     image: 'selenium/standalone-chrome'
    #     volumes:
    #         - '/dev/shm:/dev/shm'
    #     networks:
    #         - sail
    mysql:
        image: 'mysql:8.0'
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
        volumes:
            - 'sailmysql:/var/lib/mysql'
        networks:
            - sail
        healthcheck:
          test: ["CMD", "mysqladmin", "ping"]
#    pgsql:
#        image: postgres:13
#        ports:
#            - '${FORWARD_DB_PORT:-5432}:5432'
#        environment:
#            PGPASSWORD: '${DB_PASSWORD:-secret}'
#            POSTGRES_DB: '${DB_DATABASE}'
#            POSTGRES_USER: '${DB_USERNAME}'
#            POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
#        volumes:
#            - 'sailpostgresql:/var/lib/postgresql/data'
#        networks:
#            - sail
#        healthcheck:
#          test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}"]
    redis:
        image: 'redis:alpine'
        ports:
            - '${FORWARD_REDIS_PORT:-6379}:6379'
        volumes:
            - 'sailredis:/data'
        networks:
            - sail
        healthcheck:
          test: ["CMD", "redis-cli", "ping"]
    # memcached:
    #     image: 'memcached:alpine'
    #     ports:
    #         - '11211:11211'
    #     networks:
    #         - sail
    mailhog:
        image: 'mailhog/mailhog:latest'
        ports:
            - '${FORWARD_MAILHOG_PORT:-1025}:1025'
            - '${FORWARD_MAILHOG_DASHBOARD_PORT:-8025}:8025'
        networks:
            - sail
networks:
    sail:
        driver: bridge
volumes:
    sailmysql:
        driver: local
#    sailpostgresql:
#        driver: local
    sailredis:
        driver: local

As linhas com # estão comentadas, o que quer dizer que não estão ativadas, para habilitar o acesso ao Laravel Dusk precisamos descomentar o nó selenium e a linha - selenium dentro de depends_on do service laravel.test, o arquivo final:

# For more information: https://laravel.com/docs/sail
version: '3'
services:
    laravel.test:
        build:
            context: ./vendor/laravel/sail/runtimes/8.0
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: sail-8.0/app
        ports:
            - '${APP_PORT:-80}:80'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
        volumes:
            - '.:/var/www/html'
        networks:
            - sail
        depends_on:
            - mysql
            # - pgsql
            - redis
            - selenium
    selenium:
        image: 'selenium/standalone-chrome'
        volumes:
            - '/dev/shm:/dev/shm'
        networks:
            - sail
    mysql:
        image: 'mysql:8.0'
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
        volumes:
            - 'sailmysql:/var/lib/mysql'
        networks:
            - sail
        healthcheck:
          test: ["CMD", "mysqladmin", "ping"]
#    pgsql:
#        image: postgres:13
#        ports:
#            - '${FORWARD_DB_PORT:-5432}:5432'
#        environment:
#            PGPASSWORD: '${DB_PASSWORD:-secret}'
#            POSTGRES_DB: '${DB_DATABASE}'
#            POSTGRES_USER: '${DB_USERNAME}'
#            POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
#        volumes:
#            - 'sailpostgresql:/var/lib/postgresql/data'
#        networks:
#            - sail
#        healthcheck:
#          test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}"]
    redis:
        image: 'redis:alpine'
        ports:
            - '${FORWARD_REDIS_PORT:-6379}:6379'
        volumes:
            - 'sailredis:/data'
        networks:
            - sail
        healthcheck:
          test: ["CMD", "redis-cli", "ping"]
    # memcached:
    #     image: 'memcached:alpine'
    #     ports:
    #         - '11211:11211'
    #     networks:
    #         - sail
    mailhog:
        image: 'mailhog/mailhog:latest'
        ports:
            - '${FORWARD_MAILHOG_PORT:-1025}:1025'
            - '${FORWARD_MAILHOG_DASHBOARD_PORT:-8025}:8025'
        networks:
            - sail
networks:
    sail:
        driver: bridge
volumes:
    sailmysql:
        driver: local
#    sailpostgresql:
#        driver: local
    sailredis:
        driver: local

Agora é só digitar sail down e em seguida sail up e pronto, Laravel Dusk disponível.

Para executar os testes do Dusk, basta usa o comando a seguir.

sail dusk

Pré-visualização de email

Os emails dentro do projeto podem ser monitorados e interceptados pelo MailHog, ele já vem configurado, só é necessário configurar o Laravel para usá-lo e isso pode ser feito com 2 linhas no .env.

MAIL_HOST=mailhog
MAIL_PORT=1025

Para ver os emails enviados pelo Laravel acesse o MailHog na seguinte url:

http://localhost:8025

Acessar o Container Docker com Laravel

Pra quem tem mais experiência com Docker e precisa acessar o Container por algum motivo, saiba que isso é outro processo bem simples:

sail shell

Ou se precisar do Tinker:

sail tinker

Outras coisas legais

Ainda existem outras features que o Laravel Sail possui e eu não mostrei aqui, como trocar a versão do PHP, tunelamento (compartilhar um link com a internet) do seu localhost e publicar uma imagem customizada da sua aplicação, para tal de uma olhada na documentação oficial.

https://laravel.com/docs/sail

Conclusão

E é isso ai, Laravel Sail é uma excelente ferramenta para gerir seu ambiente de desenvolvimento e quem sabe até ser o ponta-pé inicial para você migrar de vez para o Docker.

Obrigado por me ler este artigo e até a próxima!

Autor: Erik Figueiredo

Músico, gamer amador, tutor de programação, desenvolvedor freelancer full cycle, com foco em PHP (Laravel e CakePHP), Javascript (Front e Node.js), Dart (Front e Flutter) e infra.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *