Como pode ser entendido a partir do artigo anterior, eu trabalhei em diferentes projetos. Os primeiros dias na nova equipe costumam ser iguais: o backend se junta a mim e realiza ações mágicas para instalar e implantar o aplicativo. O Docker é indispensável para os front-enders, já que o backend é frequentemente escrito em uma ampla gama de stacks como PHP/Java/Python/C#, e o front-end não precisa desviar a atenção do backend a cada vez para instalar e implantar tudo. Apenas em um lugar eu vi a combinação Docker-Jenkins com implantação transparente, logs e testes automatizados integrados.
Há muitos artigos detalhados sobre o Docker. Este artigo abordará a implantação de uma Aplicação de Página Única usando VueJS/Vue Router, com a parte do servidor em formato de RESTful API com NodeJS, e o MongoDB como banco de dados. O Docker Compose é utilizado para descrever e iniciar vários aplicativos-contêineres.
Por que o Docker é necessário
O Docker permite automatizar o processo de implantação do aplicativo. O desenvolvedor não precisa mais instalar programas manualmente ou lutar contra a incompatibilidade de versões em sua máquina. Basta instalar o Docker e digitar 1-2 comandos no console. É mais conveniente fazer isso no Linux.
Começando
Instalando e
Estrutura de pastas
Criamos 2 pastas para os aplicativos cliente e servidor. O arquivo com a extensão .yml é a configuração Docker Compose, onde os contêineres do aplicativo são definidos e vinculados.
Docker-compose.yml:
version: "3"
services:
mongo:
container_name: mongo
hostname: mongo
image: mongo
ports:
- "27017:27017"
server:
build: server/
#command: node ./server.js #aqui você pode sobrescrever o CMD do Dockerfile em /server
ports:
- "3000:3000"
links:
- mongo
client:
build: client/
#command: http-server ./dist #aqui você pode sobrescrever o CMD do Dockerfile em /client
network_mode: host
ports:
- "8089:8089"
depends_on:
- server
Criamos 3 serviços no Docker: para NodeJS, MongoDB e para os arquivos estáticos no Vue. Para conectar o cliente ao servidor, foi adicionado depends on server. Para o link MongoDB com a API do servidor, é utilizado links mongo. Server, client, mongo — são os nomes dos serviços.
Cliente em VueJS
Na pasta /client o aplicativo está localizado em VueJS. O aplicativo foi criado com . Ao construir a imagem, o aplicativo cliente é montado em um conjunto de arquivos estáticos na pasta /dist. O Dockerfile descreve um conjunto de comandos para construir a imagem:
FROM node:10
WORKDIR /client
COPY ./package*.json ./
RUN npm install
RUN npm install -g http-server
COPY . .
RUN npm run build
EXPOSE 8081
CMD ["npm", "test:dev"]
Observe que o package.json é copiado e instalado separadamente dos outros arquivos do projeto. Isso é feito para otimização, permitindo que o conteúdo da pasta /node_modules seja armazenado em cache durante a recompilação. Cada linha de comando é armazenada em cache separadamente.
No final, ao iniciar o contêiner, é executado o comando npm run dev. Este comando está descrito no package.json:
"scripts": {
"test:dev": "http-server dist -p 8081 -c 1 --push-state"
}
Para executar os arquivos da pasta /dist, é instalado globalmente http-server, e no dev-dependencies o pacote spa-http-server, para que o Vue Router funcione corretamente. A flag —push-state redireciona para o index.html. A flag -c com o valor de 1 segundo foi adicionada para http-server não armazenar em cache os scripts. Este é um exemplo de teste; em um projeto real, é melhor usar o nginx.
No Vuex store, criamos o campo apiHost: 'http://localhost:3000', onde é especificada a porta da API NodeJS. A parte cliente está pronta. Agora, todas as requisições do cliente para o backend vão para esta URL.
API do servidor NodeJS
Na pasta /server criamos server.js e o Dockerfile:
FROM node:10
WORKDIR /server
COPY ./package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Em server.js indica-se url para o banco de dados const url = 'mongodb://mongo:27017/';. Permitimos requisições cross-domain do cliente:
const clientUrl = 'http://localhost:8081';
const corsOptions = {
origin: clientUrl,
optionsSuccessStatus: 200, // alguns navegadores legados (IE11, várias SmartTVs) têm problemas com 204
};
app.use(cors());
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', clientUrl);
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
app.get('/getProducts', cors(corsOptions), (req, res) => {
products.getContent
.then(data => res.json(data), err => res.json(err));
});
app.get('/getUsers', cors(corsOptions), (req, res) => {
db.getUsers()
.then(data => res.json(data), err => res.json(err));
});
Conclusão
Agora vamos para o diretório do projeto e iniciar docker-compose build para a construção das imagens e docker-compose up para iniciar os contêineres. O comando levantará 3 contêineres: server, client, mongo. Para o servidor em NodeJS, pode-se configurar hot-reload, conectando-o com a pasta user. E o cliente, em fase de desenvolvimento, deve ser executado localmente com hot reload, iniciando separadamente servidor e mongo. Para iniciar um serviço separado, basta especificar seu nome docker-compose up client. Não esqueça de fazer às vezes prune e remover contêineres (containers), redes (networks) e imagens (images), para liberar recursos.
O código completo pode ser conferido . O projeto ainda está em fase de desenvolvimento.
Fonte: habr.com
