Node no Docker - ZeTheGreat/iotNodeJS GitHub Wiki
Nesta página vamos criar uma aplicação Node usando Express dentro do Docker, sem muito papo vamos começar!
Para nós criarmos nossa imagem, antes temos que criar um projeto na máquina, setar, e depois copiar para o contêiner.
Primeiro passo é criar um diretório para segurar nosso projeto, lembre-se crie dentro da home de seu usuário não root.
mkdir nome_projeto
Navegue até o diretório:
cd nome_projeto
Agora que você esta na raiz de seu projeto, agora vamos criar um arquivo chamado packge.json
, aonde nós vamos gerenciar nossas dependências.
nano package.json
A partir disso vamos escrever as settings básicas para o funcionamento do NPM.
{
"name": "nodejs-image-demo",
"version": "1.0.0",
"description": "nodejs image demo",
"author": "Nexus <[email protected]>",
"license": "MIT",
"main": "app.js",
"keywords": [
"nodejs",
"bootstrap",
"express"
],
"dependencies": {
"express": "^4.16.4"
}
}
Importante: Veja que o express é sua única dependência e que a versão dela é ^4.16.4, para saber mais sobre versionamento: link.
Agora dentro do diretório base rode:
npm install
Isso irá instalar os pacotes que você listou no seu arquivo package.json no diretório do seu projeto.
Primeiro arquivo vamos criar um arquivo js, para definir as rotas do projeto, chamaremos de app.js
nano app.js
A primeira parte do arquivo é responsável por criar aplicação Exprress e os objetos Router, assim definindo o diretório base, a porta e o host como variáveis:
var express = require("express");
var app = express();
var router = express.Router();
var path = __dirname + '/views/';
const PORT = 3000;
const HOST = '0.0.0.0';
Nestas linhas o require
está chamando o express, e através desta chamada podemos instanciar o app e router, que por suas vezes irão definir o
- path: Define o diretório base, aonde estarão as views;
- host: Por padrão executara na 0.0.0.0;
- port: Porta da aplicação: 3000.
Sabendo disso vamos definir o router
:
router.use(function (req,res,next) {
console.log("/" + req.method);
next();
});
router.get("/",function(req,res){
res.sendFile(path + "index.html");
});
router.get("/sharks",function(req,res){
res.sendFile(path + "sharks.html");
});
Importante: isto ocorre no mesmo arquivo app.js
Agora que temos a rota iremos deixar claro para aonde essa rota irá nos levar:
app.use(express.static(path));
app.use("/", router);
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
Importante: isto ocorre no mesmo arquivo app.js
Assim finalizamos o arquivo app.js
, salve e feche o arquivo.
Agora vamos criar um html apenas para testar nossa aplicação, porem, antes vamos criar o seu diretório especificado antes no texto:
mkdir views
Agora vamos criar e editar uma pagina dentro da pasta views:
nano views/index.html
Adicione o html a seguir para o teste da aplicação:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Node</title>
<meta charset="utf-8">
</head>
<body>
<h1>Bem vindo ao mundo do Node.js :)</h1>
</body>
</html>
Antes de rodar nossa aplicação para teste, devemos liberar a porta que vamos utilizar digitando:
sudo ufw allow 3000
ou
iptables -I INPUT 1 -p tcp --dport 3000 -j ACCEPT
sudo iptables-save > /etc/iptables_rules
/sbin/iptables-restore < /etc/iptables_rules
Para mais informações sobre o segundo método aqui
Importante: Basicamente a diferença entre os dois métodos é que o ufw é uma ferramenta para facilitar o uso do firewall, já o iptables é uma ferramenta antiga do Linux para gerenciamento do Firewall, mas no final os dois acabam tendo o mesmo resultado.
Após liberar a porta, vá até o diretório raiz de sua aplicação e rode a linha:
node app.js
Vá até seu navegador e coloque:
ip_do_seu_servidor:3000
Importante: Caso você não saiba como achar o seu IP, vá em seu kernel e digite:
sudo apt install net-tools
ifconfig
OutPut:
eno1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.35 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::227:eff:fe0a:b8ce prefixlen 64 scopeid 0x20<link>
ether 00:27:0e:0a:b8:ce txqueuelen 1000 (Ethernet)
RX packets 16841 bytes 5928305 (5.9 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8638 bytes 1081113 (1.0 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 20 memory 0xfe400000-fe420000
Aparecerá algo assim, e o seu IP sera o numero em frente ao inet no caso do exemplo é 192.168.0.35
Parabéns sua aplicação rodou, agora é hora de colocar ela dentro do Docker, para isso pare o processamento do servidor com ctrl + c
Seu Dockerfile especifica o que será incluído no contêiner de sua aplicação quando for executado.
Então no diretório raiz do projeto, crie o Dockerfile:
nano Dockerfile
As imagens do Docker são criadas usando uma sucessão de imagens em camadas que são construídas umas sobre as outras. Nosso primeiro passo será adicionar a imagem base para a nossa aplicação que formará o ponto inicial da construção da aplicação.
Importante: A partir daqui todos os códigos serão rodados pelo Docker ou dentro da máquina Docker.
Usaremos a imagem base node:11, pois é a versão mais atual em 12/abril/2019, data deste passo a passo:
FROM node:10
Esta imagem inclui Node.js e npm. Cada Dockerfile deve começar com uma instrução FROM.
Por padrão, a imagem Node do Docker inclui um usuário não-root node que você pode usar para evitar a execução de seu contêiner de aplicação como root, que por sua vez trás muitos riscos a aplicação.
Agora vamos ciar uma pasta dentro do Docker para servir de base para nossa aplicação e vamos dentro dela criar outra pasta para agrupar as dependências do projeto chamada node_modules. Logo após isso vamos dar direito ao node para mexer na pasta.
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
Vamos agora setar nossa worktable no nosso diretório dentro do Docker:
WORKDIR /home/node/app
Agora vamos copiar o package.json que nós criamos la atrás e usaremos o npm para ele povoar nossa pasta node_modules com as dependências:
COPY package*.json ./
RUN npm install
Agora copiar a nossa aplicação da máquina servidor para o Docker:
COPY . .
Para garantir que os arquivos da aplicação sejam de propriedade do usuário não-root node, copie as permissões do diretório da aplicação para o diretório no container:
COPY --chown=node:node . .
Defina o usuário para node:
USER node
Exponha a porta 3000
no container e inicie a aplicação:
EXPOSE 3000
CMD [ "node", "app.js" ]
O Dockerfile completo será
FROM node:11
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
RUN npm install
COPY . .
COPY --chown=node:node . .
USER node
EXPOSE 3000
CMD [ "node", "app.js" ]
Salve e feche o arquivo quando terminar a edição.
Agora antes de continuar devemos criar um arquivo de documentos que na hora de executar o comando COPY . .
o Docker deve ignorar.
Então crie .dockerignore:
nano .dockerignore
Dentro dele vamos falar para ele ignorar:
node_modules
npm-debug.log
Dockerfile
.dockerignore
Importante: Se você estiver trabalhando com o Git, então você também vai querer adicionar o seu diretório .git e seu arquivo .gitignore.
Agora devemos rodar este Dockerfile, usando o comando build do Docker e o parâmetro -t para nomear nossa imagem.
docker build -t usuário_dockerhub/nome-repositorio .
O .
significa que o contexto do build é o diretório atual.
Importante: Caso não saiba como como criar um repositorio aqui está o link
Depois disso vamos verificar nas images:
docker images
Você verá a seguinte saída:
REPOSITORY TAG IMAGE ID CREATED SIZE
seu_usuário_dockerhub/nodejs-image-demo latest 1c723fb2ef12 8 seconds ago 895MB
node
Agora que temos a image vamos criar um contêiner utilizando o docker run
-
-p: Isso publica a porta no contêiner e a mapeia para uma porta em nosso host. Usaremos a porta 80 no host, mas sinta-se livre para modificá-la, se necessário, se tiver outro processo em execução nessa porta. Para obter mais informações sobre como isso funciona, consulte esta discussão nos documentos do Docker sobre port binding.
-
-d: Isso executa o contêiner em segundo plano.
-
--name: Isso nos permite dar ao contêiner um nome memorizável.
Execute o seguinte comando para construir o contêiner:
docker run --name nodes_ubuntu -p 3000:3000 -d usuário_dockerhub/nome-repositorio
Depois que seu contêiner estiver em funcionamento, você poderá inspecionar uma lista de contêineres em execução com docker ps
:
docker ps
OutPut:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e50ad27074a7 usuário_dockerhub/nome-repositorio "node app.js" 8 seconds ago Up 7 seconds 0.0.0.0:3000->3000/tcp nodes_ubuntu
Agora é só acessar sua aplicação utilizando o IP do seu servidor
.
A primeira etapa para enviar a imagem é efetuar login na conta do Docker Hub que você criou nos pré-requisitos:
docker login -u seu_usuário_dockerhub -p senha_do_usuário_dockerhub
Importante: Efetuando o login dessa maneira será criado um arquivo ~/.docker/config.json no diretório home do seu usuário com suas credenciais do Docker Hub.
Agora você pode enviar a imagem da aplicação para o Docker Hub usando a tag criada anteriormente:
docker push usuário_dockerhub/nome-repositorio
Isso é tudo pessoal.
Caso você queira mais detalhes este passo a passo foi baseado neste link