Como habilitar o recarregamento ao vivo em aplicativos baseados no Docker com volumes do Docker

Requer o Node.js. versão 10 ou superior e o MongoDB. Em vez de instalar o MongoDB em sua máquina de ambiente local, você o instalará usando o Docker. Você também o expõe no localhost: 27017 para que os aplicativos que não estão em execução no Docker possam acessá-lo sem conhecer o endereço IP interno do Docker.

Copie o comando abaixo e cole-o no seu terminal:

docker run --name mongodb -p 27017:27017 -d mongo:4

Usando o comando acima, ele fará o download e executará o MongoDB instância. Observe que, se você já tiver uma instância com esse nome, ocorrerá um erro sobre o nome inválido. Se você vir o erro, execute docker rm mongodb e removerá qualquer instância anterior para que você possa executar o comando docker run novamente.

Cavando no aplicativo

O arquivo README.md diz que você precisa de uma instância do MongoDB em execução antes de iniciar o aplicativo, juntamente com o Node.js. Se você tiver o Node.js instalado, acesse o nodejs-with-mongodb-api-example pasta e execute os seguintes comandos:

npm i 
npm run build 
npm start

Depois de executar esses comandos, você pode acessar um navegador em http: // localhost: 3000 e veja o aplicativo em execução, como mostra a imagem abaixo:

Lembre-se de que o aplicativo já possui um comando para ativar a atualização ao vivo, que é npm run dev:watch. O pipeline deve refletir as seguintes etapas:

  1. Desenvolvedor altera arquivos TypeScript;
  2. Arquivos transcritos transcritos para Javascript;
  3. O servidor percebe alterações no Javascript e reinicia o servidor Node.js.

Portanto, o espelhamento de arquivos nos contêineres do Docker refletirá todas as alterações no contêiner. o npm run build:watch do aplicativo capturará as alterações e gerará arquivos de saída na lib pasta para que o npm run dev:run reiniciará o servidor toda vez que for acionado.

Dockerizing aplicativos

Se o Docker é um mundo completamente novo para você, não tenha medo! Você irá configurá-lo do zero. Você precisará criar alguns arquivos para iniciar:

  1. Dockerfile – um arquivo de recibo que lista como instalar e executar seu aplicativo;
  2. .dockerignore – um arquivo que lista quais arquivos não serão incluídos na instância do contêiner do Docker.

Criando o Dockerfile

O Dockerfile é o conceito chave aqui. Lá você especifica as etapas e dependências para preparar e executar o aplicativo. Enquanto você ler o arquivo README.md, será fácil implementar o arquivo de recebimento.

Vou colocar o arquivo inteiro abaixo e cavar depois. Na tua nodejs-with-mongodb-api-example pasta criar um Dockerfile e cole o código abaixo:

FROM node:14-alpine

WORKDIR /src

ADD package.json /src 

RUN npm i --silent

ADD . /src 

RUN npm run build 

CMD npm start

O que está acontecendo lá?

  • Na linha 1 – utiliza como base de imagem o Node.js 14 – versão alpina;
  • Das linhas 2 a 4 – copia e instala dependências do Node.js. do host para o contêiner. Observe que a ordem é importante. Adicionar package.json à pasta src antes de restaurar as dependências armazenará em cache e impedirá a instalação de pacotes toda vez que você precisar criar sua imagem;
  • Das linhas 6 a 7 – Executa comandos para o processo de compilação e, em seguida, para iniciar o programa conforme mencionado no arquivo README.md.

Ignorando arquivos desnecessários com .dockerignore

Ademais, estou trabalhando em um sistema baseado em OSX e o contêiner do Docker será executado em um sistema baseado no Linux Alpine. Quando você executa o npm install ele restaurará dependências para ambientes específicos.

Agora você criará um arquivo para ignorar o código gerado da sua máquina local, como node_modules e lib. Portanto, quando você copia todos os arquivos do diretório atual para o contêiner, ele não obtém versões de pacotes inválidas.

No nodejs-with-mongodb-api-example pasta criar um .dockerignore e cole o código abaixo:

node_modules/
lib/

Construindo a imagem da janela de encaixe

Eu prefiro executar este aplicativo a partir do rootFolder. Volte para o post-docker-live-reload pasta e execute os seguintes comandos para preparar uma imagem para uso posterior:

docker build -t app nodejs-with-mongodb-api-example

Observe que o comando acima usa o -t para indicar o nome da imagem e, logo em seguida, a pasta que contém o Dockerfile Arquivo.

Trabalhando com volumes

Antes de executar o aplicativo, vamos fazer alguns hacks para melhorar nossa experiência nos contêineres do Docker.

Os volumes do Docker são um recurso para espelhar arquivos através da máquina local e do ambiente do Docker. Você também pode compartilhar volumes em contêineres e reutilizá-los para armazenar em cache dependências.

Seu objetivo é assistir a quaisquer alterações nos locais .ts arquivos e espelhar essas alterações no contêiner. Mesmo que os arquivos e os node_modules pasta estão no mesmo caminho.

Você se lembra quando eu disse que as dependências em cada sistema operacional seriam diferentes? Para garantir que nosso ambiente local não afete o ambiente do Docker ao espelhar arquivos, isolaremos o contêiner node_modules pasta em um volume distinto.

Consequentemente, ao criar o node_modules pasta no contêiner, ele não criará a pasta no ambiente da máquina local. Execute o comando abaixo no seu terminal para criá-lo:

docker volume create --name nodemodules

Executando e ativando o recarregamento ao vivo

Como você sabe, o npm run dev:watch especificado no arquivo README.md mostra como ativar o recarregamento ao vivo. O problema é que você está codificando em uma máquina local e ela deve refletir diretamente seu contêiner.

Ao executar os seguintes comandos, você vinculará seu ambiente local ao contêiner do Docker para que qualquer alteração no nodejs-with-mongodb-api-example afetará o contêiner src pasta.

docker run 
    --name app 
    --link mongodb 
    -e MONGO_URL=mongodb 
    -e PORT=4000 
    -p 4000:4000 
    -v `pwd`/nodejs-with-mongodb-api-example:/src 
    -v nodemodules:/src/node_modules 
    app npm run dev:watch

Vamos nos aprofundar no que está acontecendo lá:

  • --link está dando permissão ao aplicativo para acessar a instância do MongoDB;
  • -e – são as variáveis ​​de ambiente. Conforme mencionado no arquivo README.md você pode especificar a cadeia de conexão do MongoDB à qual deseja se conectar substituindo o MONGO_URL variável. Substitua o PORT variável se você deseja executá-lo em uma porta diferente. Observe que o valor mongodb é o mesmo nome que usamos para criar nossa instância do MongoDB nas seções anteriores. Esse valor também é um alias para o IP da instância interna do MongoDB;
  • -v – mapeia o diretório atual para o contêiner do Docker usando um volume virtual. Usando o pwd comando, você pode obter o caminho absoluto para o diretório de trabalho atual e a pasta que deseja espelhar no contêiner do Docker. Tem o :/src. o src caminho é o WORKDIR instrução definida em Dockerfile portanto, espelhamos a pasta local no src do contêiner do Docker;
  • -v – o segundo volume refletirá o volume individual que criamos no contêiner node_modules pasta;
  • app – o nome da imagem;
  • npm run dev:watch – este último comando substituirá o CMD instruções do Dockerfile.

Após executar o comando abaixo, você pode acionar o navegador após alterar o local Index.ts arquivo para ver os resultados. O vídeo abaixo demonstra essas etapas na prática.

Empacotando

Você sabe que trabalhar com comandos shell funciona. Mas não é tão comum usá-los aqui e não é produtivo para executar todos esses comandos, criar imagens e gerenciar instâncias manualmente. Então componha!

A composição do Docker é uma maneira de simplificar a agregação e vinculação de serviços. Você pode especificar os bancos de dados, logs, aplicativos, volumes, redes e assim por diante.

Primeiro, você precisa remover todas as instâncias ativas para evitar conflitos nas portas expostas. Execute os seguintes comandos no seu terminal para remover volumes, serviços e contêineres:

docker rm app 
docker volume rm nodemodules
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)

O arquivo docker-compose

Crie um docker-compose.yml arquivo no seu post-docker-livereload pasta usando os dados abaixo:

version: '3'
services:
    mongodb:
        image: mongo:4
        ports:
            - 27017:27017
    app:
        build: nodejs-with-mongodb-api-example
        command: npm run dev:watch
        ports:
            - 4000:4000
        environment: 
            MONGO_URL: mongodb
            PORT: 4000
        volumes:
            - ./nodejs-with-mongodb-api-example:/src/
            - nodemodules:/src/node_modules
        links:
            - mongodb
        depends_on: 
            - mongodb

volumes:
    nodemodules: {}

O arquivo acima especifica recursos por seções. Observe que você tem links e depends_on seções lá. O campo links é o mesmo sinalizador que você usou no seu comando shell. O Depend_on garantirá que o MongoDB seja uma dependência para a execução do seu aplicativo. Ele executará o MongoDB antes do seu aplicativo como mágica!

Voltando ao seu terminal, para iniciar todos os serviços e criar a imagem do Docker e criar volumes e serviços de link, execute o seguinte comando:

docker-compose up --build

Se você precisar remover todos os serviços criados anteriormente por esse Dockerfile você também pode correr docker-compose down.

Docker é seu amigo!

Está certo, meu amigo. O Docker pode ajudar a evitar muitos erros possíveis antes que eles aconteçam. Você pode usá-lo para aplicativos front-end e back-end. Mesmo para a IoT quando você precisa controlar o hardware, pode especificar políticas para usá-lo.

Como próximas etapas, recomendo que você dê uma olhada em orquestradores de contêineres, como o Kubernetes e o Docker swarm. Eles podem melhorar ainda mais seus aplicativos existentes e ajudá-lo a passar para o próximo nível.

Obrigado pela leitura

Eu realmente aprecio o tempo que passamos juntos. Espero que este conteúdo seja mais do que apenas texto. Espero que ajude a torná-lo um pensador melhor e também um programador melhor. Siga-me Twitter e confira meu blog pessoal onde eu compartilho todo o meu conteúdo valioso.

Até mais! 🍻