Encaixando um aplicativo criado com base no React, Express e MongoDB

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 Dockerfilee 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 pai

Reagir 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 Dockerfileno 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.jsone 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 nginxresultados 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 Dockerfileterá 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 Dockerfileno 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 Dockerfileque 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 8080na 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 apie cliento contêiner que contêm o MongoDB. Para fazer isso, usaremos o arquivo docker-compose.ymllocalizado no diretório raiz do repositório pai. Isso é feito devido ao fato de que, a partir deste local, há acesso a arquivos Dockerfilepara 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 projeto

Agora vamos adicionar osdocker-compose.ymlseguintes 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, apie 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 apie clientexiste uma chave buildcujo valor contém o caminho para os arquivos dos Dockerfileserviços correspondentes (para os diretórios raiz apie client). As portas do contêiner atribuídas nos arquivos Dockerfileserã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.ymlseguinte 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?


All Articles