
Em projetos de médio e grande porte, o site não se limita a um serviço - por exemplo, apenas um site, como regra, há um banco de dados, uma API, um servidor que roteia solicitações para todos esses serviços. A implantação e atualização de tudo isso sem padronização não é fácil, e a expansão para muitos servidores é ainda mais difícil.
O Docker, que se tornou o padrão de fato no mundo dos aplicativos de embalagem, entrega e publicação, nos ajudará a resolver esse problema.
O Docker nos permite agrupar um aplicativo ou serviço com todas as dependências e configurações em um contêiner isolado, garantindo a consistência do conteúdo em qualquer plataforma.
Como um aplicativo isomórfico, usaremos a estrutura Nuxt.js, que consiste em Vue.js e Node.js, permitindo escrever aplicativos da Web universais com renderização do lado do servidor (SSR).
Essa opção é devido à preferência pessoal, no entanto, da mesma maneira, você pode usar qualquer outra estrutura, por exemplo, Next.js.
Coletamos e publicamos a primeira imagem.
Primeiro de tudo, você precisa configurar a porta e o host dentro do aplicativo. Existem várias
maneiras de fazer isso. Usaremos as configurações em package.json adicionando uma nova seção:
"config": { "nuxt": { "host": "0.0.0.0", "port": "3000" } }
Para ações posteriores, precisamos do docker, docker-compone instalado no sistema e um editor com um projeto aberto.
Crie um Dockerfile que colocamos na raiz e descreva as instruções para criar a imagem.
Precisamos construir a imagem com base na imagem da versão 10 do Node.js. Nesse caso, a versão leve do alpine é usada:
FROM node:10-alpine
Em seguida, defina a variável de ambiente com o nome do diretório:
ENV APP_ROOT /web
Defina como o diretório de trabalho e adicione a fonte:
WORKDIR ${APP_ROOT} ADD . ${APP_ROOT}
Instale as dependências e construa o aplicativo:
RUN npm ci RUN npm run build
E escrevemos o comando de inicialização do aplicativo dentro da imagem:
CMD ["npm", "run", "start"]
Dockerfile FROM node:10-alpine ENV APP_ROOT /web ENV NODE_ENV production WORKDIR ${APP_ROOT} ADD . ${APP_ROOT} RUN npm ci RUN npm run build CMD ["npm", "run", "start"]
Depois disso, abra a pasta atual no terminal e colete a imagem:
docker build -t registry.gitlab.com/vik_kod/nuxtjs_docker_example .
Execute a imagem localmente para verificar se tudo funciona corretamente:
docker run -p 3000:3000 registry.gitlab.com/vik_kod/nuxtjs_docker_example
Indo para
localhost: 3000, devemos ver o seguinte:

Ótimo! Iniciamos com sucesso a produção construindo o aplicativo na máquina local.
Agora, precisamos publicar a imagem no repositório do docker para usar a imagem montada finalizada no servidor de destino. Você pode usar um repositório auto-hospedado ou qualquer outro, por exemplo, o
hub.docker.com oficial.
Vou usar o repositório no gitlab, a guia com repositórios docker é chamada de registro. Anteriormente, eu já criei um repositório para o projeto, então agora eu executo o comando:
docker push registry.gitlab.com/vik_kod/nuxtjs_docker_example
Após a inicialização da imagem, você poderá começar a configurar o servidor VPS,
o meu é o seguinte:
- 1 GB de RAM
- 4 núcleos
- Unidade de 30 GB
Também aproveitei a oportunidade para instalar o docker imediatamente ao criar o servidor; portanto, se ele não estiver instalado no seu VPS, você poderá ler as instruções no
site oficial.Depois de criar o servidor, vá para ele e efetue login no repositório do docker, no meu caso é o gitlab:
docker login registry.gitlab.com
Após a autorização, podemos iniciar o aplicativo com o comando visto anteriormente:
docker run -p 3000:3000 registry.gitlab.com/vik_kod/nuxtjs_docker_example

A imagem foi baixada e iniciada, vamos verificar:

Vemos uma imagem familiar, lançamos o contêiner com o aplicativo, mas já no servidor remoto.
O toque final permaneceu; agora, quando o terminal estiver fechado, a imagem será interrompida; portanto, adicionaremos o atributo -d para iniciar o contêiner em segundo plano.
Pare e reinicie:
docker run -d -p 3000:3000 registry.gitlab.com/vik_kod/nuxtjs_docker_example
Agora podemos fechar o terminal e garantir que nosso aplicativo esteja funcionando com sucesso.
Conseguimos o que era necessário - lançamos o aplicativo no docker e agora ele é adequado para implantação, como imagem independente e como parte de uma infraestrutura maior.
Adicionar proxy reverso
No estágio atual, podemos publicar projetos simples, mas e se precisarmos colocar o aplicativo e a API no mesmo domínio e, além disso, fornecer as estatísticas não através do Node.js.
Assim, surge a necessidade do chamado servidor proxy reverso, para o qual todas as solicitações serão recebidas e redirecionadas, dependendo da solicitação para serviços relacionados.
Como servidor, usaremos o nginx.
Gerenciar contêineres se houver mais de um individualmente não é muito conveniente. Portanto, usaremos o docker-compose como uma maneira de organizar e gerenciar contêineres.
Crie um novo projeto vazio, na raiz do qual adicionamos o arquivo docker-compose.yml e a pasta nginx.
No docker-compose.yml, escrevemos o seguinte:
version: "3.3" # services: # , nginx nginx: image: nginx:latest # 80 http 443 https ports: - "80:80" - "443:443" # container_name: proxy_nginx volumes: # nginx , - ./nginx:/etc/nginx/conf.d # - ./logs:/var/log/nginx/ # Nuxt.js nuxt: # image: registry.gitlab.com/vik_kod/nuxtjs_docker_example container_name: nuxt_app # ports: - "3000:3000"
Na pasta nginx, adicione a configuração, recomendada pelo site oficial
Nuxt.js , com pequenas alterações.
nginx.conf map $sent_http_content_type $expires { "text/html" epoch; "text/html; charset=utf-8" epoch; default off; } server { root /var/www; listen 80; # nginx server_name localhost; # ip gzip on; gzip_types text/plain application/xml text/css application/javascript; gzip_min_length 1000; location / { expires $expires; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 1m; proxy_connect_timeout 1m; # , # docker-compose , nuxt_app proxy_pass http://nuxt_app:3000; } }
Executamos o comando para executar:
docker-compose up

Tudo começou corretamente, agora, se formos para o endereço que está ouvindo o nginx, localhost - veremos nosso aplicativo, não haverá diferenças visuais, mas agora todas as solicitações vão para o nginx primeiro, onde são redirecionadas, dependendo das regras especificadas.
Agora não temos serviços ou estatísticas adicionais, vamos adicionar uma pasta estática na qual colocaremos alguma imagem.
Monte-o no contêiner nginx adicionando uma linha ao docker-compose:
... container_name: proxy_nginx volumes: # - ./static:/var/www/static ...
Docker-compose.yml atualizado version: "3.3" # services: # , nginx nginx: image: nginx:latest # 80 http 443 https ports: - "80:80" - "443:443" # container_name: proxy_nginx volumes: # nginx , - ./nginx:/etc/nginx/conf.d # - ./logs:/var/log/nginx/ # - ./static:/var/www/static # Nuxt.js nuxt: # image: registry.gitlab.com/vik_kod/nuxtjs_docker_example container_name: nuxt_app # ports: - "3000:3000"
Em seguida, adicione o novo local ao nginx.conf:
location /static/ { try_files $uri /var/www/static; }
Nginx.conf atualizado map $sent_http_content_type $expires { "text/html" epoch; "text/html; charset=utf-8" epoch; default off; } server { root /var/www; listen 80; # nginx server_name localhost; # ip gzip on; gzip_types text/plain application/xml text/css application/javascript; gzip_min_length 1000; location / { expires $expires; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 1m; proxy_connect_timeout 1m; # , # docker-compose , nuxt_app proxy_pass http://nuxt_app:3000; } location /static/ { try_files $uri /var/www/static; } }
Reinicie a janela de encaixe-composição:
docker-compose up --build
Vá para
localhost / static / demo.jpg

Agora, as estatísticas são fornecidas pelo Nginx, removendo a carga do Node.js no aplicativo principal.
Depois de garantir que tudo funcione, você pode publicar nossa montagem no servidor. Para fazer isso, vou criar um repositório no diretório atual. Tendo adicionado anteriormente os logs e a pasta estática ao .gitignore.
Depois disso, vamos ao servidor, paramos a imagem do docker que foi lançada anteriormente e clonamos o repositório.

Antes de iniciar a montagem, você precisa mover a pasta com as estáticas para o servidor, acessar o terminal na máquina local e usar o utilitário de linha de comando scp para mover a pasta para o servidor:
scp -r /Users/vik_kod/PhpstormProjects/nuxtjs_docker_proxy_example/static root@5.101.48.172:/root/example_app/
Se o volume de estática for grande, é melhor compactar primeiro a pasta e enviá-la como um arquivo morto e depois descompactá-la no servidor. Caso contrário, o download poderá demorar muito tempo.
Retornamos ao terminal no servidor e vamos para a pasta clonada, execute o comando:
docker-compose up -d
Feche o terminal e acesse o site:


Ótimo! Usando o proxy reverso, separamos a estática do aplicativo.
Passos adicionais
Tudo o que fizemos acima é uma opção bastante simples; em grandes projetos, você precisa considerar mais coisas; abaixo está uma pequena lista do que você pode fazer a seguir.
- Contêineres de dados apenas para áreas administrativas estáticas, aplicativos SPA e bancos de dados
- Serviços adicionais para processamento e otimização de imagens, por exemplo
- Integração de CI / CD, montagem da imagem ao avançar para a ramificação selecionada, bem como atualização automática e reinicialização de serviços
- Crie um cluster Kubernetes ou Swarm se houver mais de 1 servidor, para balanceamento de carga e fácil dimensionamento horizontal
Total
- Publicamos o aplicativo com sucesso no servidor e o preparamos para mais redimensionamentos.
- Conhecemos o docker e tivemos uma idéia de como agrupar seu aplicativo em um contêiner.
- Aprendemos quais medidas podem ser tomadas ainda mais para melhorar a infraestrutura.
Código fonte
AppConfigsObrigado por sua atenção e espero que este material tenha ajudado!