Executando verificação de segurança...
3

Criando uma aplicação node com proxy reverso usando nginx

Neste artigo vamos criar um proxy reverso utilizando nginx e também vamos criar uma aplicação com o node diretamente de um container.

Criando a aplicação node

O primeiro passo é criar um diretório, vamos chamar esse diretório de nodeapp e acessar ele

mkdir nodeapp && cd nodeapp

Agora vamos abrir esse diretório em uma ide ou editor de texto, no meu caso abri no VS Code

code .

Agora crie um diretório chamado node para criarmos nossa aplicação node ali dentro.

Feito isso vamos executar uma imagem docker com o node na sua última versão, também vamos fazer com que o diretório /usr/src/app aponte para o diretório que criamos e que estamos acessando no VS Code, pra isso vamos executar o seguinte comando:

docker run --rm -it -v $(pwd)/node:/usr/src/app -p 3000:3000 node:15 bash

Explicando o comando:

docker run

  • executa uma imagem docker qualquer

--rm

  • o cotainer será destruído ao parar de ser executado

--it

  • ativa o modo interativo para que possamos acessar o shell bash e interagir com o container

-v $(pwd)/:/usr/src/app

  • mapeamos um volume e dizer que o diretóio em que esamos agora $(pwd) vai ser mapeado para o diretório /usr/src/app

-p 3000:3000

  • especifica que o container deverá expor a porta 3000 e redirecionar o tráfego da porta externa 3000 para a porta interna 3000

node:latest

  • por fim estamos dizendo qual imagem queremos, nesse caso node na sua última versão disponível

bash

  • estamos falando que o modo interativo deve executar o born again shell (bash)

Após fazer isso estaremos dentro do container, você deverá ver algo mais ou menos assim:

root@25e599b36ad1:/# 

Vamos nos dirigir ao diretório mapeado para o nosso volume

cd /usr/src/app

E finalmente criar uma aplicação node para isso digite

npm init

Após preencher os campos você deverá notar que foi criado um arquivo chamado package.json

O próximo passo será instalar o express

npm install express --save

Após esse comando você verá que agora temos um diretório chamado node_modules e os arquivos package.json e package-lock.json

Agora crie um arquivo chamado index.js

Nesse arquivos vamos configurar uma aplicação node bem simples:

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
    res.send('<h1>It Works !</h1>')
})

app.listen(port, () => {
    console.log('Running on ' + port);
})

E vamos executar nossa aplicação pra ver se está funcionando

node index.js

Após esse comando acesse http://localhost:3000/ e você verá uma página com o cabeçalho "It Works !"

OK nossa aplicação está pronta, pressione CTRL+C para parar a aplicação e vamos sair do container:

exit

Apesar de sairmos do container veja que os arquivos permaneceram no VS Code e temos uma estrutura mais ou menos assim:

nodeapp
└── node
    ├── node_modules
    ├── index.js
    ├── package-lock.json
    └── package.json

Criando a imagem da aplicação

Vamos criar uma imagem para o nosso container de aplicação node, pra isso crie um Dockerfile dentro do diretório node

Nesse Dockerfile vams querer utilizar a última versão do node e vamos utilizar multi stage building também.

FROM node:latest AS build

WORKDIR /usr/src/app

COPY . .

FROM node:15-alpine

WORKDIR /usr/src/app

COPY --from=build /usr/src/app .

RUN npm install

EXPOSE 3000

CMD ["node", "index.js"]

FROM node:latest AS build

  • Especifica que vamos utilizar a última versão do node para fazer o build da imagem

WORKDIR /usr/src/app

  • Definimos o diretório /usr/src/app como diretório de trabalho do nosso container

COPY . .

  • Estamos copiado tudo que está no diretório atual para o workdir definido acima

FROM node:15-alpine

  • A partir daqui começa o build da imagem final na qual vamos utilizar na imagem final a versão node:15-alpine

WORKDIR /usr/src/app

  • Definimos o diretório /usr/src/app como diretório de trabalho do nosso container

COPY --from=build /usr/src/app .

  • Estamos copiando tudo que está no diretório /usr/src/app da build acima para o workdir atual

RUN npm install

  • Executamos o comando npm install

EXPOSE 3000

  • Vamos deixar a porta 3000 exposta

CMD ["node", "index.js"]

  • Por fim vamos executar o comando node index.js

Veja que fizemos no Dockerfile praticamente tudo que fizemos no container para executar a nossa aplicação.

Agora basta gerar a imagem

docker build -t jorgerabello/nodeapp .

Criando um proxy reverso com nginx

Nesse temos a seguinte estrutura

nodeapp
└── node
    ├── node_modules
    ├── index.js
    ├── package-lock.json
    └── package.json

Vamos criar um diretório chamado nginx de modo que nossa estrutura fique assim:

nodeapp
├── nginx
└── node
    ├── node/index.js
    ├── node/node_modules
    ├── node/package-lock.json
    └── node/package.json

Dentro do diretório nginx vamos criar um arquivo de configuração chamado nginx.conf com o seguinte conteúdo:

server {
    listen 80;
    server_name app;

    location / {
        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_pass http://app:3000/#;
    }
}

server {:

  • Define um bloco de configuração para um servidor.

listen 80;:

  • Especifica que o servidor deve escutar na porta 80.

server_name app;:

  • Define o nome do servidor como "app". Isso significa que o servidor responderá a solicitações para esse nome de domínio.

location / {:

  • Define uma localização dentro do servidor onde as configurações específicas serão aplicadas. Neste caso, as configurações se aplicam a todas as solicitações (todas as rotas).

As próximas linhas dentro do bloco de localização são diretivas para configurar o proxy reverso:

proxy_set_header Host $host;:

  • Define o cabeçalho Host da solicitação HTTP para o valor do cabeçalho Host recebido pelo Nginx.

proxy_set_header X-Real-IP $remote_addr;:

  • Define o cabeçalho X-Real-IP para o endereço IP real do cliente.

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;:

  • Adiciona o endereço IP do cliente ao cabeçalho X-Forwarded-For, preservando os endereços IP anteriores, se houver.

proxy_set_header X-Forwarded-Proto $scheme;:

  • Define o cabeçalho X-Forwarded-Proto para o esquema (HTTP ou HTTPS) da solicitação original.

proxy_pass http://app:3000/;:

  • Define para onde o Nginx deve encaminhar as solicitações. Neste caso, as solicitações serão encaminhadas para "http://app:3000/". Isso é comumente usado para encaminhar solicitações para um servidor de aplicativos em execução em outra porta ou máquina.

Agora temos a seguinte estrutura

nodeapp
├── nginx
│   └── nginx/nginx.conf
└── node
    ├── node/index.js
    ├── node/node_modules
    ├── node/package-lock.json
    └── node/package.json

Vamos criar um Dockerfile para o container do nginx

FROM nginx:1.15.0-alpine

RUN rm /etc/nginx/conf.d/default.conf

COPY nginx.conf /etc/nginx/conf.d/

RUN mkdir /var/www/html -p && touch /var/www/html/index.html

Esse é um dockerfile bem simples onde:

FROM nginx:1.15.0-alpine:

  • Vamos utilizar a imagem nginx:1.15.0-alpine

RUN rm /etc/nginx/conf.d/default.conf

  • Estamos removendo o arquivo de configuração padrão chamado default.conf

COPY nginx.conf /etc/nginx/conf.d/

  • Estamos copiando o arquivo nginx.conf que acabamos de criar para o diretório onde ficam os arquivos de configuração do nginx

RUN mkdir /var/www/html -p && touch /var/www/html/index.html

  • Por fim estamos criar um diretório /var/www/html e dentro dele criando o arquivo index.html que é necessário para o nginx executar.

Buildando a imagem do nginx

docker build -t jorgerabello/nginx:reverseproxy .  

Podemos conferir se as imagens foram criadas

REPOSITORY             TAG            IMAGE ID       CREATED          SIZE
jorgerabello/nodeapp   latest         b7e295a5152d   44 seconds ago   116MB
jorgerabello/nginx     reverseproxy   287ea2b92516   2 hours ago      18MB

Por fim temos a seguinte estrutura de diretórios:

nodeapp
├── nginx
│   ├── nginx/Dockerfile
│   └── nginx/nginx.conf
└── node
    ├── node/Dockerfile
    ├── node/index.js
    ├── node/node_modules
    ├── node/package-lock.json
    └── node/package.json

Faça o upload das suas images para o docker hub

docker push jorgerabello/nodeapp:latest 
docker push jorgerabello/nginx:reverseproxy 

Na raiz vamos criar um docker-compose.yaml para executar nossos containers

version: '3'

networks:
  nodeappnet:
    driver: bridge

services:
  app:
    build:
      context: ./node
      dockerfile: Dockerfile
    networks:
      - nodeappnet
    volumes:
      - ./node:/usr/src/app
      - node_modules:/usr/src/app/node_modules
    tty: true
    container_name: nodeapp
    image: jorgerabello/nodeapp
    ports:
      - "3000:3000"
  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    image: jorgerabello/nginx:reverseproxy
    container_name: nginx
    networks:
      - nodeappnet
    ports:
      - "8080:80"
    depends_on:
      - app      
volumes:
  node_modules:

Esse é um docker-compose.yaml bem elementar onde executamos os containers pelas suas imagens, caso você tenha dúvidas sobre docker-compose pode consultar a documentação aqui ou ler esse artigo sobre docker compose.

Executando tudo

Por fim temos a seguinte estrutura de diretórios

nodeapp
├── docker-compose.yaml
├── nginx
│   ├── nginx/Dockerfile
│   └── nginx/nginx.conf
└── node
    ├── node/Dockerfile
    ├── node/index.js
    ├── node/node_modules
    ├── node/package-lock.json
    └── node/package.json

No diretório node app vamos utilizar o nosso docker-compose

docker-compose up -d

E podemos verificar que os containers estão executando

docker ps
CONTAINER ID   IMAGE                             COMMAND                  CREATED         STATUS         PORTS                                       NAMES
af908e4147ad   jorgerabello/nginx:reverseproxy   "nginx -g 'daemon of…"   4 seconds ago   Up 4 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp       nginx
f7d9b08df4a5   jorgerabello/nodeapp              "docker-entrypoint.s…"   4 seconds ago   Up 4 seconds   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   nodeapp

Agora se acessarmos http://localhost:8080/ seremos redirecionado para a aplicação node.

Se você quiser provar a si mesmo que o redirecionamento está acontecendo pare o container da aplicação node e tente acessar novamente na porta 8080 e você receberá um belíssimo 503 Bad Gateway.

Para parar o container da aplicação utilize:

docker rm -f f7d9b08df4a5

Finalizando

Bom pessoal nesse artigo usamos algumas features bem legais do docker:

  • Criamos uma aplicação node diretamente do container
  • Criamos um proxy reverso com nginx
  • Construímos imagens dos 2 containers e colocamos no docker hub
  • Executamos os containers fazendo com que acessando o nginx sermos redirecionados para a aplicação node

Valeu e até a próxima !

Carregando publicação patrocinada...
0