Watch | Docker
- Watch | Docker
Depois de muitos anos de pedidos, finalmente a Docker resolveu implementar um watch mode no comando compose! Com ele a gente vai poder iniciar uma espécie de atualização automática dos nossos containers sempre que nossos arquivos forem modificados no disco!
O problema
Um dos maiores problemas para quem usava (ou até usa) o Docker compose, é que, sempre que temos nosso cluster de containers ativo, e estamos desenvolvendo localmente com um desses containers, quando fazemos uma modificação em algum dos arquivos do projeto, precisamos reiniciar todo o compose para criar a nova imagem.
Geralmente, quando estamos fazendo uma API externa, por exemplo, não temos tanto esse problema porque podemos rodar a API em si fora do compose, enquanto apontamos para dentro dos containers de dependências, por exemplo, de alguma API externa ou algo do tipo. Mas, as vezes, isso não é possível, geralmente quando precisamos que seja o que for que a gente está fazendo fique na mesma rede do Docker, ou então precise estar rodando dentro de um container. Nesse caso, a única saída é rodar tudo dentro do Docker compose.
Porém, sempre que a gente atualiza um dos arquivos do projeto, temos que rodar aquele famoso docker compose down seguido de um docker compose up --rebuild para poder reconstruir o nosso serviço e continuar desenvolvendo.
A solução
Por muitos anos, a galera sugeriu que o docker compose tivesse um modo watch, ou seja, um modo que pudesse ouvir o que está acontecendo com um determinado arquivo ou conjunto de arquivos do projeto e rodar um comando específico quando eles forem alterados. Depois de alguns anos, temos o compose file watch mode. E o mais legal é que você não precisa habilitar ele para todos os seus serviços.
Isso permite que a gente agora comece a desenvolver diretamente dentro dos containers do compose, tornando o ambiente muito mais fácil de ser migrado de um lado para o outro, independente se o seu projeto precisa ou não de uma integração direta com o Docker.
Para ativar o modo watch basta que você coloque a chave watch em qualquer serviço dentro do seu docker-compose.yml. Essa chave leva um array de objetos com duas propriedades, uma é o path e o outra é a action, basicamente o serviço vai tomar uma action quando tiver uma mudança em um determinado path.
Vamos a um exemplo:
services:
web:
build: .
command: npm run dev
x-develop:
watch:
- action: sync
path: ./web
target: /src/web
ignore:
- node_modules
YAML
Copy
No momento, o compose watch mode está em estado experimental, por isso temos que usar a chave
x-develop
Actions
Existem dois tipos de actions pré definidas que você pode tomar: sync e rebuild:
Sync
Esse tipo de ação vai garantir que qualquer mudança feita no seu arquivo local, fora do container, seja adicionada ao container e substitua o arquivo que está dentro dele.
É muito parecido com o conceito de bind mounts, ou até mesmo de volumes, que continuam existindo dentro do Docker, mas, ao contrário deles, você tem uma granularidade maior com o Sync do que com os volumes. Um exemplo disso é justamente poder ignorar arquivos ou diretórios inteiros, coisa que não podemos fazer a não ser que tivéssemos múltiplos volumes.
Um caso de uso muito interessante disso é justamente no nosso amado JavaScript, especialmente com Node.js, o ideal é que a gente ignore completamente a pasta node_modules porque, por mais que a gente tenha muito código JS lá dentro, algumas dependências usam Native Modules, que não vão funcionar em ambientes diferentes do que eles foram criados e compilados para executar.
Rebuild
Quando usamos o Rebuild, vamos ter o equivalente de rodar docker compose up --build <serviço> sempre que salvarmos o path.
Enquanto o sync é mais recomendado para aplicações que podem fazer um hot reload, isto é, recarregar a aplicação já é suficiente para poder verificar as modificações, como um front-end ou algo do tipo, o rebuild é mais indicado para quando temos uma modificação em algum arquivo chave (tipo o package.json) que precisa de uma recompilação da imagem para reinstalar ou remover dependências que podem ter sido modificadas.
Outro caso de uso é para linguagens compiladas, que precisam passar pelo processo completo de build para serem refeitas, embora existam casos onde você pode somente trocar o binário de uma aplicação que será suficiente.
Path e Target
Ambas as ações vão acompanhadas de duas outras propriedades, o path e o target.
Em resumo, o target é o caminho do arquivo observado dentro do container, por exemplo, se meu arquivo package.json está na raiz da minha pasta local, mas dentro da pasta /app do meu container, então meu target será /app/package.json.
Lembrando que, por regra, todos os caminhos são baseados no diretório de build da sua aplicação, ou seja, o local onde o docker encontrou o Dockerfile
Executando
Para executar o docker compose watch, primeiramente precisamos criar a build do nosso serviço com docker compose up -d --build --wait, isso fará com que o docker inicie o compose e construa todas as imagens.
Depois, podemos rodar docker compose alpha watch para iniciar o watch mode que vai ler as configurações que queremos do nosso arquivo.