O autor do artigo, cuja tradução estamos publicando hoje, quer falar sobre como compactar aplicativos da Web baseados em React, Express e MongoDB em contêineres do Docker. Aqui, consideraremos os recursos para formar a estrutura de arquivos e pastas desses projetos, criar arquivos Dockerfile
e usar a tecnologia Docker Compose.
Início do trabalho
Por uma questão de simplicidade, presumo que você já tenha um aplicativo em funcionamento, apresentado pelas partes do cliente e do servidor, conectado ao banco de dados.É melhor se o código do cliente e do servidor estiver localizado na mesma pasta. O código pode estar localizado em um repositório, mas pode ser armazenado em repositórios diferentes. Neste caso, os projectos devem ser combinadas em uma pasta utilizando o comando git submodule
. Eu fiz exatamente isso.Árvore de arquivos do repositório paiReagir Aplicação
Aqui, usei um projeto criado usando o aplicativo Create React e configurado para oferecer suporte ao TypeScript. Este é um blog simples, contendo vários elementos visuais.Primeiro, crie um arquivo Dockerfile
no diretório raiz client
. Para fazer isso, basta executar o seguinte comando:$ touch Dockerfile
Abra o arquivo e insira os comandos abaixo. Como já mencionado, eu uso no meu aplicativo TypeScript, então preciso construí-lo primeiro. Então você precisa pegar o que aconteceu e implantar tudo no formato de recursos estáticos. Para conseguir isso, eu uso o processo de duas etapas para criar uma imagem do Docker.A primeira etapa é usar o Node.js para criar o aplicativo. Eu uso, como imagem de base, uma imagem alpina. Esta é uma imagem muito compacta, que afetará beneficamente o tamanho do contêiner.FROM node:12-alpine as builder
WORKDIR /app
COPY package.json /app/package.json
RUN npm install --only=prod
COPY . /app
RUN npm run build
Então começa o nosso Dockerfile
. Primeiro vem a equipe node:12-alpine as builder
. Em seguida, definimos o diretório de trabalho - no nosso caso, isso /app
. Por esse motivo, uma nova pasta será criada no contêiner. Nesta pasta do contêiner, copie package.json
e instale as dependências. Em seguida /app
, copiamos tudo da pasta /services/client
. O trabalho é concluído pela montagem do projeto.Agora você precisa organizar a hospedagem para o assembly recém-criado. Para fazer isso, use o NGINX. E, novamente, esta será a versão alpina do sistema. Estamos fazendo isso, como antes, para economizar espaço.FROM nginx:1.16.0-alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Aqui, os nginx
resultados da montagem do projeto obtidos na etapa anterior são copiados para a pasta . Em seguida, abra a porta 80
. É nessa porta que o contêiner aguardará as conexões. A última linha do arquivo é usada para iniciar o NGINX.Isso é tudo o que é necessário para encaixar a parte do cliente do aplicativo. O resultado Dockerfile
terá a seguinte aparência:FROM node:12-alpine as build
WORKDIR /app
COPY package.json /app/package.json
RUN npm install --only=prod
COPY . /app
RUN npm run build
FROM nginx:1.16.0-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
API Express
Nossa API Express também é bastante simples. Aqui, para organizar os pontos de extremidade, a tecnologia RESTful é usada. Os pontos de extremidade são usados para criar publicações, dar suporte à autorização e resolver outros problemas. Vamos começar criando Dockerfile
no diretório raiz api
. Vamos agir como antes.Durante o desenvolvimento do lado do servidor do aplicativo, usei os recursos do ES6. Portanto, para executar o código, preciso compilá-lo. Decidi processar o código usando Babel. Como você deve ter adivinhado, aqui novamente o processo de montagem em várias etapas será usado.FROM node:12-alpine as builder
WORKDIR /app
COPY package.json /app/package.json
RUN apk --no-cache add --virtual builds-deps build-base python
RUN npm install
COPY . /app
RUN npm run build
Tudo aqui é muito parecido com o Dockerfile
que usamos para a parte do cliente do projeto, portanto não entraremos em detalhes. No entanto, há um recurso:RUN apk --no-cache add --virtual builds-deps build-base python
Antes de armazenar senhas no banco de dados, eu as misturo usando bcrypt . Este é um pacote muito popular, mas há alguns problemas em usá-lo em imagens baseadas em Alpine. Aqui você pode encontrar algo como as seguintes mensagens de erro:node-pre-gyp WARN Pre-built binaries not found for bcrypt@3.0.8 and node@12.16.1 (node-v72 ABI, musl) (falling back to source compile with node-gyp)
npm ERR! Failed at the bcrypt@3.0.8 install script.
Esse é um problema amplamente conhecido. Sua solução é instalar pacotes adicionais e Python antes de instalar pacotes npm.O próximo passo na criação da imagem, como no caso do cliente, é pegar o que foi formado na etapa anterior e executá-la usando o Node.js.FROM node:12-alpine
WORKDIR /app
COPY --from=builder /app/dist /app
COPY package.json /app/package.json
RUN apk --no-cache add --virtual builds-deps build-base python
RUN npm install --only=prod
EXPOSE 8080
USER node
CMD ["node", "index.js"]
Há outro recurso aqui, que consiste em instalar apenas os pacotes projetados para o projeto funcionar na produção. Não precisamos mais da Babel - afinal, tudo já foi compilado na primeira etapa da montagem. Em seguida, abrimos a porta 8080
na qual o lado do servidor do aplicativo aguardará a chegada das solicitações e executamos o Node.js.Aqui está o resumo Dockerfile
:FROM node:12-alpine as builder
WORKDIR /app
COPY package.json /app/package.json
RUN apk --no-cache add --virtual builds-deps build-base python
RUN npm install
COPY . /app
RUN npm run build
FROM node:12-alpine
WORKDIR /app
COPY --from=builder /app/dist /app
COPY package.json /app/package.json
RUN apk --no-cache add --virtual builds-deps build-base python
RUN npm install --only=prod
EXPOSE 8080
USER node
CMD ["node", "index.js"]
Docker compor
A última fase do nosso trabalho é trazer os contêineres api
e client
o contêiner que contêm o MongoDB. Para fazer isso, usaremos o arquivo docker-compose.yml
localizado no diretório raiz do repositório pai. Isso é feito devido ao fato de que, a partir deste local, há acesso a arquivos Dockerfile
para as partes cliente e servidor do projeto.Crie um arquivo docker-compose.yml
:$ touch docker-compose.yml
A estrutura do arquivo do projeto agora deve se parecer com a abaixo.A estrutura final dos arquivos do projetoAgora vamos adicionar osdocker-compose.yml
seguintes comandos:version: "3"
services:
api:
build: ./services/api
ports:
- "8080:8080"
depends_on:
- db
container_name: blog-api
client:
build: ./services/client
ports:
- "80:80"
container_name: blog-client
db:
image: mongo
ports:
- "27017:27017"
container_name: blog-db
Tudo é organizado de maneira muito simples. Temos três serviços: client
, api
e db
. Não há seleção para o MongoDB Dockerfile
- o Docker baixará a imagem apropriada do hub e criará um contêiner. Isso significa que nosso banco de dados estará vazio, mas para iniciantes, isso nos convém.Nas seções api
e client
existe uma chave build
cujo valor contém o caminho para os arquivos dos Dockerfile
serviços correspondentes (para os diretórios raiz api
e client
). As portas do contêiner atribuídas nos arquivos Dockerfile
serão abertas na rede hospedada no Docker Compose. Isso permitirá que os aplicativos interajam. Ao configurar o serviço api
, além disso, a chave é usadadepends_on
. Ele diz ao Docker que antes de iniciar este serviço, é necessário aguardar até que o contêiner seja iniciado completamente db
. Graças a isso, podemos evitar erros no contêiner api
.E - aqui está outra coisinha relacionada ao MongoDB. Na base de código de back-end, você precisa atualizar a cadeia de conexão do banco de dados. Geralmente indica localhost
:mongodb://localhost:27017/blog
Mas, usando a tecnologia Docker Compose, precisamos apontar para o nome do contêiner:mongodb://blog-db:27017/blog
A etapa final do nosso trabalho é iniciar tudo isso executando o docker-compose.yml
seguinte comando na pasta raiz do projeto (onde o arquivo está localizado ):$ docker-compose up
Sumário
Analisamos uma técnica simples para contêiner de aplicativos com base em React, Node.js e MongoDB. Acreditamos que, se você precisar, poderá adaptá-lo facilmente aos seus projetos.PS Lançamos o mercado no site da RUVDS. A imagem do Docker é instalada em um clique. Você pode verificar a operação de contêineres no VPS . Os novos clientes recebem 3 dias gratuitamente para testes.Queridos leitores! Você usa o Docker Compose?