Conteinerizando um aplicativo Laravel 6 para o desenvolvimento com o Docker Compose no Ubuntu 18.04

Introdução

Conteinerizar um aplicativo se refere ao processo de adaptar um aplicativo e seus componentes com a finalidade de conseguir executá-lo em ambientes leves, conhecidos como contêineres. Esses ambientes são isolados e descartáveis e podem ser aproveitados para o desenvolver, testar e implantar aplicativos para a produção.

Neste guia, usaremos o Docker Compose para conteinerizar um aplicativo Laravel 6 para o desenvolvimento. Quando você tiver terminado, terá um aplicativo de demonstração Laravel funcionando em três contêineres de serviço separados:

  • Um serviço de app executando o PHP7.4-FPM;
  • Um serviço de db executando o MySQL 5.7;
  • Um serviço de nginx que usa o serviço app para analisar o código PHP antes de entregar o aplicativo Laravel para o usuário final.

Para permitir um processo de desenvolvimento simplificado e facilitar a depuração do aplicativo, manteremos os arquivos do aplicativo em sincronia, usando volumes compartilhados. Também veremos como usar os comandos docker-compose exec para executar o Composer e o Artisan no contêiner do app.

Pré-requisitos

  • Acesso a uma máquina local com Ubuntu 18.04, ou um servidor de desenvolvimento como um usuário não raiz com privilégios para o comando sudo. Se estiver usando um servidor remoto, é recomendável ter um firewall ativo instalado. Para preparar tudo isso, consulte nosso Guia de configuração inicial de servidor para o Ubuntu 18.04.
  • O Docker instalado no seu servidor, seguindo os Passos 1 e 2 do artigo sobre Como instalar e usar o Docker no Ubuntu 18.04.
  • O Docker Compose instalado no seu servidor, seguindo o Passo 1 do artigo sobre Como instalar o Docker Compose no Ubuntu 18.04.

Passo 1 — Obtendo o aplicativo Demo

Para começar, vamos buscar o aplicativo demo do Laravel do seu repositório do Github. Estamos interessados na ramificação do tutorial-01, que contém o aplicativo básico do Laravel que criamos no primeiro guia desta série.

Para obter o código do aplicativo compatível com este tutorial, baixe a versão tutorial-1.0.1 para seu diretório home com:

  • cd ~
  • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip

Vamos precisar do comando unzip para descompactar o código do aplicativo. Caso não tenha instalado esse pacote antes, faça isso agora com:

  • sudo apt update
  • sudo apt install unzip

Agora, descompacte os conteúdos do aplicativo e renomeie o diretório desempacotado para ter um acesso mais fácil:

  • unzip travellist.zip
  • mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo

Navegue até o diretório travellist-demo:

  • cd travellist-demo

No próximo passo, vamos criar um arquivo de configuração .env para configurar o aplicativo.

Passo 2 — Configurando o arquivo .env do aplicativo

Os arquivos de configuração do Laravel estão localizados em um diretório chamado config, dentro do diretório raiz do aplicativo. Além disso, um arquivo .env é usado para preparar a configuração dependente do ambiente, como credenciais e quaisquer informações que possam variar entre as implantações. Esse arquivo não está incluído no controle de revisão.

Aviso: o arquivo de configuração de ambiente contém informações confidenciais sobre o seu servidor, incluindo credenciais para o banco de dados e chaves de segurança. Por esse motivo, nunca compartilhe esse arquivo publicamente.

Os valores contidos no arquivo .env terão precedência sobre os valores definidos nos arquivos de configuração regulares, localizados no diretório config. Cada instalação em novo ambiente exige um arquivo de ambiente personalizado para definir coisas como as configurações da conexão com o banco de dados, as opções de depuração, a URL do aplicativo, entre outros itens que possam variar, dependendo do ambiente em que o aplicativo esteja funcionando.

Agora, vamos criar um novo arquivo .env para personalizar as opções de configuração do ambiente de desenvolvimento que estamos preparando. O Laravel vem com um exemplo de arquivo do .env que podemos copiar para criar o nosso:

  • cp .env.example .env

Abra este arquivo usando o nano ou outro editor de texto de sua escolha:

  • nano .env

O arquivo .env atual do aplicativo demo travellist contém as configurações para usar um banco de dados local do MySQL, com o 127.0.0.1 como o host do banco de dados. Precisamos atualizar a variável DB_HOST para que ela aponte para o serviço de banco de dados que vamos criar em nosso ambiente do Docker. Neste guia, vamos chamar nosso serviço de banco de dados de db. Vá em frente e substitua o valor listado de DB_HOST pelo nome do serviço de banco de dados:

.env

APP_NAME=Travellist APP_ENV=dev APP_KEY= APP_DEBUG=true APP_URL=http://localhost:8000  LOG_CHANNEL=stack  DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=password ... 

Caso queira, sinta-se à vontade para alterar o nome do bando de dados, nome de usuário e senha. Essas variáveis serão aproveitadas em um próximo passo, onde iremos definir o arquivo docker-compose.yml para configurar nossos serviços.

Salve o arquivo quando terminar de editar. Se você usou o nano, você pode fazer isso pressionando Ctrl+x, depois Y e Enter para confirmar.

Passo 3 — Configurando o Dockerfile do aplicativo

Embora ambos os nossos serviços do MySQL e do Nginx se baseiem em imagens padronizadas, obtidas a partir do Docker Hub,ainda precisaremos compilar uma imagem personalizada para o contêiner do aplicativo. Criaremos um novo Dockerfile para isso.

Nossa imagem do travellist irá basear-se na imagem oficial do PHP, php:7.4-fpm​​​ do Docker Hub. Além desse ambiente básico do PHP-FPM, instalaremos alguns módulos adicionais do PHP e a ferramenta de gerenciamento de dependência do Composer.

Também iremos criar um novo usuário do sistema; isso é necessário para executar comandos do artisan e do composer durante o desenvolvimento do aplicativo. A configuração do uid garante que o usuário dentro do contêiner tenha o mesmo uid que o usuário do sistema no seu computador host, onde você estiver executando o Docker. Dessa forma, quaisquer arquivos criados por esses comandos são replicados no host com as permissões corretas. Isso também significa que você poderá usar o editor de códigos de sua escolha no computador host para desenvolver o aplicativo que está executando dentro dos contêineres.

Crie um novo Dockerfile com:

  • nano Dockerfile

Copie o seguinte conteúdo para o seu Dockerfile:

Dockerfile

FROM php:7.4-fpm  # Arguments defined in docker-compose.yml ARG user ARG uid  # Install system dependencies RUN apt-get update && apt-get install -y      git      curl      libpng-dev      libonig-dev      libxml2-dev      zip      unzip  # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/*  # Install PHP extensions RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd  # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer  # Create system user to run Composer and Artisan Commands RUN useradd -G www-data,root -u $uid -d /home/$user $user RUN mkdir -p /home/$user/.composer &&      chown -R $user:$user /home/$user  # Set working directory WORKDIR /var/www  USER $user  

Não se esqueça de salvar o arquivo quando terminar.

Nosso Dockerfile começa pela definição da imagem base que estamos usando: php:7.4-fpm.

Após instalar os pacotes do sistema e as extensões do PHP, instalaremos o Composer, copiando o executáve composer de sua última imagem oficial para nossa imagem do aplicativo.

Então, um novo usuário do sistema é criado e configurado usando os argumentos user e uid que foram declarados no início do Dockerfile. Esses valores serão injetados pelo Docker Compose no momento da compilação.

Por fim, definimos o dir padrão em funcionamento como /var/www e trocamos para o usuário recém-criado. Isso garantirá que, ao executar os comandos do composer e do artisan no contêiner do aplicativo, você esteja se conectando como um usuário comum e que esteja no diretório correto.

Passo 4 — Configurando os arquivos de configuração do Nginx e os arquivos de despejo do banco de dados

Ao criar ambientes de desenvolvimento com o Docker Compose, com frequência, é necessário compartilhar os arquivos de configuração ou de inicialização com os contêineres de serviço, para assim configurar ou inicializar esses serviços. Essa prática facilita fazer alterações nos arquivos de configuração para ajustar seu ambiente enquanto estiver desenvolvendo o aplicativo.

Agora, vamos definir uma pasta com os arquivos que serão usados para configurar e inicializar nossos contêineres de serviço.

Para configurar o Nginx, compartilharemos um arquivo travellist.conf que configurará como o aplicativo será atendido. Crie a pasta docker-compose/nginx com:

  • mkdir -p docker-compose/nginx

Abra um novo arquivo chamado de travellist.conf dentro desse diretório:

  • nano docker-compose/nginx/travellist.conf

Copie a seguinte configuração do Nginx para aquele arquivo:

docker-compose/nginx/travellist.conf

 server {     listen 80;     index index.php index.html;     error_log  /var/log/nginx/error.log;     access_log /var/log/nginx/access.log;     root /var/www/public;     location ~ .php$ {         try_files $uri =404;         fastcgi_split_path_info ^(.+.php)(/.+)$;         fastcgi_pass app:9000;         fastcgi_index index.php;         include fastcgi_params;         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;         fastcgi_param PATH_INFO $fastcgi_path_info;     }     location / {         try_files $uri $uri/ /index.php?$query_string;         gzip_static on;     } } 

Esse arquivo irá configurar o Nginx para escutar na porta 80 e usar o index.php como a página de índice padrão. Ele definirá o diretório base como /var/www/public e, em seguida, configurará o Nginx para usar o serviço app na porta 9000 para processar os arquivos *.php.

Salve e feche o arquivo quando terminar de editar.

Para configurar o banco de dados do MySQL, compartilharemos um banco de dados de despejo que será importado quando o contêiner for inicializado. Esta é uma característica fornecida pela imagem do MySQL 5.7, que usaremos naquele contêiner.

Crie uma nova pasta para seus arquivos de inicialização do MySQL dentro da pasta docker-compose:

  • mkdir docker-compose/mysql

Abra um novo arquivo .sql:

  • nano docker-compose/mysql/init_db.sql

O arquivo de despejo do MySQL se baseia no banco de dados que configuramos em nosso guia do Laravel em LEMP. Ele criará uma nova tabela chamada places. Então, ele preencherá a tabela com um conjunto de exemplos de localidade.

Adicione o código a seguir ao arquivo:

docker-compose/mysql/db_init.sql

DROP TABLE IF EXISTS `places`;  CREATE TABLE `places` (   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,   `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,   `visited` tinyint(1) NOT NULL DEFAULT '0',   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;  INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0); 

A tabela places contém três campos: id, name e visited. O campo visited é um sinalizador utilizado para identificar os lugares que ainda não foram visitados. Sinta-se à vontade para modificar os exemplos de localidade ou incluir novos locais. Salve e feche o arquivo quando terminar.

Terminamos de configurar o Dockerfile do aplicativo e os arquivos de configuração de serviço. Em seguida, configuraremos o Docker Compose para usar esses arquivos ao criar nossos serviços.

Passo 5 — Criando um ambiente multicontêiner com o Docker Compose

O Docker Compose permite a criação de ambientes multicontêiner para os aplicativos em execução no Docker. Ele usa as definições de serviço para compilar ambientes totalmente personalizáveis com vários contêineres que podem compartilhar redes e volumes de dados. Isso permite uma integração perfeita entre os componentes do aplicativo.

Para configurar nossas definições de serviço, criaremos um novo arquivo chamado docker-compose.yml. Este arquivo fica normalmente localizado na raiz da pasta do aplicativo. Ele define seu ambiente em contêiner, incluindo as imagens base que você usará para compilar seus contêineres e como seus serviços irão interagir.

Vamos definir três serviços diferentes em nosso arquivo docker-compose.yml: app, db e nginx.

O serviço app compilará uma imagem chamada travellist, com base no Dockerfile que criamos anteriormente. O contêiner definido por esse serviço executará um servidor php-fpm para analisar o código PHP e enviará os resultados de volta para o serviço do nginx, o qual estará em execução em um contêiner separado. O serviço mysql define um contêiner que executa um servidor do MySQL 5.7. Nosso serviços irão compartilhar uma conexão de rede de ponte chamada de travellist.

Os arquivos do aplicativo serão sincronizados nos serviços do app e do nginx através de montagens associadas. As montagens bind são úteis em ambientes de desenvolvimento porque elas levam em conta um desempenho sincronizado bidirecional entre o computador host e os contêineres.

Crie um novo arquivo docker-compose.yml na raiz da pasta do aplicativo:

  • nano docker-compose.yml

Um arquivo típico do docker-compose.yml começa com uma definição de versão, seguido de um nó de services, sob o qual todos os serviços são definidos. As redes compartilhadas são geralmente definidas no final desse arquivo.

Para começar, copie este código boilerplate para o seu arquivo docker-compose.yml:

docker-compose.yml

version: "3.7" services:   networks:   travellist:     driver: bridge 

Agora, vamos editar o nó de services para incluir os serviços app, db e nginx.

O serviço app

O serviço app configurará um contêiner chamado travellist-app. Ele compila uma nova imagem do Docker com base em um Dockerfile – localizado no mesmo caminho que o arquivo docker-compose.yml. A nova imagem será salva localmente sob o nome travellist.

Embora o diretório base que está sendo atendido como o aplicativo esteja localizado no contêiner do nginx, também precisamos dos arquivos do aplicativo em algum lugar dentro do contêiner de app, para que possamos executar tarefas de linha de comando com a ferramenta Laravel Artisan.

Copie a seguinte definição de serviço sob seu nó de services, dentro do arquivo docker-compose.yml:

docker-compose.yml

  app:     build:       args:         user: sammy         uid: 1000       context: ./       dockerfile: Dockerfile     image: travellist     container_name: travellist-app     restart: unless-stopped     working_dir: /var/www/     volumes:       - ./:/var/www     networks:       - travellist 

Essas configurações fazem o seguinte:

  • build: esta configuração diz ao Docker Compose para compilar uma imagem local para o serviço app, usando o caminho especificado (contexto) e o Dockerfile para obter instruções. Os argumentos user e uid são injetados no Dockerfile para personalizar os comandos de criação de usuário no momento da compilação.
  • image: o nome que será usado para a imagem que está sendo criada.
  • container_name: define o nome do contêiner desse serviço.
  • restart: sempre reinicia, a menos que o serviço seja interrompido.
  • working_dir: define o diretório padrão para esse serviço como /var/www.
  • volumes: cria um volume compartilhado que sincronizará o conteúdo do diretório atual para o /var/www, dentro do contêiner. Note que esse não é o seu diretório raiz, uma vez que ele ficará no contêiner nginx.
  • networks: define esse serviço para usar uma rede chamada travellist.

O serviço db

O serviço db usa uma imagem de MySQL 5.7 pré-compilada do Docker Hub. Como o Docker Compose carrega automaticamente os arquivos da variável .env, localizados no mesmo diretório que o arquivo docker-compose.yml, podemos obter nossas configurações de banco de dados do arquivo .env do Laravel que criamos em um passo anterior.

Inclua a seguinte definição de serviço no nó de seus services, logo após o serviço app:

docker-compose.yml

  db:     image: mysql:5.7     container_name: travellist-db     restart: unless-stopped     environment:       MYSQL_DATABASE: ${DB_DATABASE}       MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}       MYSQL_PASSWORD: ${DB_PASSWORD}       MYSQL_USER: ${DB_USERNAME}       SERVICE_TAGS: dev       SERVICE_NAME: mysql     volumes:       - ./docker-compose/mysql:/docker-entrypoint-initdb.d     networks:       - travellist 

Essas configurações fazem o seguinte:

  • image: define a imagem do Docker que deve ser usada para este contêiner. Neste caso, estamos usando uma imagem MySQL 5.7 do Docker Hub.
  • container_name: define o nome do contêiner para este serviço: travellist-db​​​.
  • restart: sempre reinicia este serviço, a menos que ele seja explicitamente interrompido.
  • environment: define as variáveis de ambiente no novo contêiner. Estamos usando valores obtidos a partir do arquivo .env do Laravel para configurar nosso serviço do MySQL, o qual irá criar – automaticamente – um novo banco de dados e um usuário, com base nas variáveis de ambiente fornecidas.
  • volumes: cria um volume para compartilhar um arquivo de despejo de banco de dados .sql que será usado para inicializar o banco de dados do aplicativo. A imagem do MySQL importará automaticamente os arquivos .sql colocados no diretório /docker-entrypoint-initdb.d dentro do contêiner.
  • networks: define esse serviço para usar uma rede chamada travellist.

O serviço nginx

O serviço nginx usa uma imagem do Nginx pré-compilada sobre o Alpine, uma distribuição de Linux leve. Ela cria um contêiner chamado travellist-nginx e usa a definição de ports para criar um redirecionamento da porta 8000 – no sistema host – para a porta 80 – dentro do contêiner.

Inclua a seguinte definição de serviço no nó de seus services, logo após o serviço db:

docker-compose.yml

  nginx:     image: nginx:1.17-alpine     container_name: travellist-nginx     restart: unless-stopped     ports:       - 8000:80     volumes:       - ./:/var/www       - ./docker-compose/nginx:/etc/nginx/conf.d     networks:       - travellist 

Essas configurações fazem o seguinte:

  • image: define a imagem do Docker que deve ser usada para este contêiner. Neste caso, estamos usando a imagem do Alpine Nginx 1.17.
  • container_name: define o nome do contêiner para este serviço: travellist-nginx​​​.
  • restart: sempre reinicia este serviço, a menos que ele seja explicitamente interrompido.
  • ports: define um redirecionamento de porta que permitirá o acesso externo através da porta 8000 para o servidor Web em execução na porta 80, dentro do contêiner.
  • volumes: cria dois volumes compartilhados. O primeiro sincronizará o conteúdo do diretório atual para o /var/www, dentro do contêiner. Dessa forma, quando fizer alterações locais nos arquivos do aplicativo, elas serão refletidas rapidamente no aplicativo que está sendo atendido pelo Nginx, dentro do contêiner. O segundo volume garantirá que o nosso arquivo de configuração do Nginx, localizado em docker-compose/nginx/travellist.conf, seja copiado para a pasta de configuração do Nginx do contêiner.
  • networks: define esse serviço para usar uma rede chamada travellist.

Arquivo docker-compose.yml finalizado

Nosso arquivo docker-compose.yml finalizado ficará com esta aparência:

docker-compose.yml

version: "3.7" services:   app:     build:       args:         user: sammy         uid: 1000       context: ./       dockerfile: Dockerfile     image: travellist     container_name: travellist-app     restart: unless-stopped     working_dir: /var/www/     volumes:       - ./:/var/www     networks:       - travellist    db:     image: mysql:5.7     container_name: travellist-db     restart: unless-stopped     environment:       MYSQL_DATABASE: ${DB_DATABASE}       MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}       MYSQL_PASSWORD: ${DB_PASSWORD}       MYSQL_USER: ${DB_USERNAME}       SERVICE_TAGS: dev       SERVICE_NAME: mysql     volumes:       - ./docker-compose/mysql:/docker-entrypoint-initdb.d     networks:       - travellist    nginx:     image: nginx:alpine     container_name: travellist-nginx     restart: unless-stopped     ports:       - 8000:80     volumes:       - ./:/var/www       - ./docker-compose/nginx:/etc/nginx/conf.d/     networks:       - travellist  networks:   travellist:     driver: bridge 

Certifique-se de salvar o arquivo quando terminar.

Passo 6 — Executando o aplicativo com o Docker Compose

Agora, usaremos os comandos do docker-compose para compilar a imagem do aplicativo e executar os serviços que especificamos em nossa configuração.

Compile a imagem do app com o seguinte comando:

  • docker-compose build app

Esse comando pode levar alguns minutos para completar. Você verá um resultado similar a este:

OutputBuilding app Step 1/11 : FROM php:7.4-fpm  ---> fa37bd6db22a Step 2/11 : ARG user  ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459  ---> 533c30216f34 Step 3/11 : ARG uid  ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda  ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y     git     curl     libpng-dev     libonig-dev     ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer  ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user  ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1  ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer &&     chown -R $user:$user /home/$user  ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09  ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www  ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa  ---> 00ada639da21 Step 11/11 : USER $user  ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9  ---> fe176ff4702b  Successfully built fe176ff4702b Successfully tagged travellist:latest  

Quando a compilação estiver concluída, você poderá executar o ambiente em segundo plano com:

  • docker-compose up -d
OutputCreating travellist-db    ... done Creating travellist-app   ... done Creating travellist-nginx ... done 

Isso executará seus contêineres em segundo plano. Para exibir informações sobre o estado de seus serviços ativos, execute:

  • docker-compose ps

Você verá um resultado como esse:

Output      Name                    Command              State          Ports         ------------------------------------------------------------------------------- travellist-app     docker-php-entrypoint php-fpm   Up      9000/tcp             travellist-db      docker-entrypoint.sh mysqld     Up      3306/tcp, 33060/tcp travellist-nginx   nginx -g daemon off;            Up      0.0.0.0:8000->80/tcp 

Agora, seu ambiente está funcionando! Porém, ainda precisaremos executar alguns comandos para concluir a configuração do aplicativo. Você pode usar o comando docker-compose exec para executar comandos nos contêineres de serviço, como um ls -l para exibir informações detalhadas sobre os arquivos no diretório do aplicativo:

  • docker-compose exec app ls -l
Outputtotal 256 -rw-rw-r-- 1 sammy 1001    738 Jan 15 16:46 Dockerfile -rw-rw-r-- 1 sammy 1001    101 Jan  7 08:05 README.md drwxrwxr-x 6 sammy 1001   4096 Jan  7 08:05 app -rwxr-xr-x 1 sammy 1001   1686 Jan  7 08:05 artisan drwxrwxr-x 3 sammy 1001   4096 Jan  7 08:05 bootstrap -rw-rw-r-- 1 sammy 1001   1501 Jan  7 08:05 composer.json -rw-rw-r-- 1 sammy 1001 179071 Jan  7 08:05 composer.lock drwxrwxr-x 2 sammy 1001   4096 Jan  7 08:05 config drwxrwxr-x 5 sammy 1001   4096 Jan  7 08:05 database drwxrwxr-x 4 sammy 1001   4096 Jan 15 16:46 docker-compose -rw-rw-r-- 1 sammy 1001   1015 Jan 15 16:45 docker-compose.yml -rw-rw-r-- 1 sammy 1001   1013 Jan  7 08:05 package.json -rw-rw-r-- 1 sammy 1001   1405 Jan  7 08:05 phpunit.xml drwxrwxr-x 2 sammy 1001   4096 Jan  7 08:05 public -rw-rw-r-- 1 sammy 1001    273 Jan  7 08:05 readme.md drwxrwxr-x 6 sammy 1001   4096 Jan  7 08:05 resources drwxrwxr-x 2 sammy 1001   4096 Jan  7 08:05 routes -rw-rw-r-- 1 sammy 1001    563 Jan  7 08:05 server.php drwxrwxr-x 5 sammy 1001   4096 Jan  7 08:05 storage drwxrwxr-x 4 sammy 1001   4096 Jan  7 08:05 tests -rw-rw-r-- 1 sammy 1001    538 Jan  7 08:05 webpack.mix.js 

Agora, vamos executar o composer install para instalar as dependências do aplicativo:

  • docker-compose exec app composer install

Você verá um resultado como esse:

OutputLoading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals   - Installing doctrine/inflector (1.3.1): Downloading (100%)            - Installing doctrine/lexer (1.2.0): Downloading (100%)            - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)            - Installing erusev/parsedown (1.7.4): Downloading (100%)            - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%)            - Installing phpoption/phpoption (1.7.2): Downloading (100%)            - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%)            - Installing symfony/css-selector (v5.0.2): Downloading (100%)         … Generating optimized autoload files > IlluminateFoundationComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. 

A última coisa que precisamos fazer – antes de testar o aplicativo – é gerar uma chave única para o aplicativo com a artisan, a ferramenta de linha de comando do Laravel. Esta chave é usada para criptografar sessões de usuário e outros dados confidenciais:

  • docker-compose exec app php artisan key:generate
OutputApplication key set successfully. 

Agora, vá até seu navegador e acesse o nome de domínio ou endereço IP do seu servidor na porta 8000:

http://server_domain_or_IP:8000 

Você verá uma página como esta:

Demo do aplicativo Laravel

Você pode usar o comando logs para verificar os registros gerados por seus serviços:

  • docker-compose logs nginx
Attaching to travellist-nginx travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:25 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:26 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:42 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" … 

Se quiser pausar seu ambiente do Docker Compose ao mesmo tempo que mantém o estado de todos seus serviços, execute:

  • docker-compose pause
OutputPausing travellist-db    ... done Pausing travellist-nginx ... done Pausing travellist-app   ... done 

Em seguida, você poderá retomar os seus serviços com:

  • docker-compose unpause
OutputUnpausing travellist-app   ... done Unpausing travellist-nginx ... done Unpausing travellist-db    ... done 

Para fechar seu ambiente do Docker Compose e remover todos os seus contêineres, redes e volumes, execute:

  • docker-compose down
OutputStopping travellist-nginx ... done Stopping travellist-db    ... done Stopping travellist-app   ... done Removing travellist-nginx ... done Removing travellist-db    ... done Removing travellist-app   ... done Removing network travellist-laravel-demo_travellist 

Para obter um panorama de todos os comandos do Docker Compose, verifique a Referência da linha de comando do Docker Compose.

Conclusão

Neste guia, configuramos um ambiente do Docker com três contêineres, usando o Docker Compose para definir nossa infraestrutura em um arquivo YAML.

A partir deste ponto, você poderá trabalhar no seu aplicativo do Laravel sem a necessidade de instalar e configurar um servidor Web local para desenvolvimentos e testes. Além disso, você estará trabalhando com um ambiente descartável e que pode ser facilmente replicado e distribuído, o que pode ser útil ao desenvolver seu aplicativo e ao passar para um ambiente de produção.