Introdução

Este tutorial traz um passo a passo para ajudá-lo na criação de uma imagem de aplicativo para um website estático que utilize o framework Express e o Bootstrap. Em seguida, você irá compilar um contêiner usando essa imagem, irá enviá-la para o Docker Hub e a utilizará para compilar outro contêiner, demonstrando como é possível recriar e dimensionar o seu aplicativo.

Para obter uma versão mais detalhada deste tutorial, com explicações mais detalhadas de cada passo, consulte o tutorial Como compilar um aplicativo Node.js com o Docker.

Pré-requisitos

docker illustration for: Pré-requisitos

Para seguir este tutorial, você vai precisar do seguinte:

  • Um usuário sudo em seu servidor ou em seu ambiente local.
  • O Docker.
  • Node.js e npm.
  • Uma conta do Docker Hub.

Passo 1 — Instalando as dependências do seu aplicativo

Primeiro, crie um diretório para seu projeto em seu diretório home do usuário não raiz:

				
					
mkdir <^>node_project<^>

				
			

Navegue até este diretório:

				
					
cd <^>node_project<^>

				
			

Esse é o diretório raiz do projeto.

Em seguida, crie um package.json com as dependências do seu projeto:

				
					
nano package.json

				
			

Adicione as seguintes informações sobre o projeto ao arquivo; certifique-se de substituir as informações do autor pelo seu nome e detalhes de contato:

				
					
[label ~/node_project/package.json]

{

  "name": "<^>nodejs-image-demo<^>",

  "version": "1.0.0",

  "description": "nodejs image demo",

  "author": "<^>Sammy the Shark <sammy@example.com><^>",

  "license": "MIT",

  "main": "app.js",

  "scripts": {

    "start": "node app.js",

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [

    "nodejs",

    "bootstrap",

    "express"

  ],

  "dependencies": {

    "express": "^4.16.4"

  }

}

				
			

Instale as dependências do seu projeto:

				
					
npm install

				
			

Passo 2 — Criando os arquivos do aplicativo

Criaremos um site que fornece informações aos usuários sobre tubarões.

Abra o app.js no diretório principal do projeto para definir as rotas do projeto:

				
					
nano app.js

				
			

Adicione o conteúdo a seguir ao arquivo para criar o aplicativo Express e os objetos Router, definir o diretório base, a porta e o host como variáveis, definir as rotas e, em seguida, montar o middleware router junto com os ativos estáticos do aplicativo:

				
					
[label ~/node_project/app.js]

var express = require("express");

var app = express();

var router = express.Router();



var path = __dirname + '/views/';



// Constants

const PORT = 8080;

const HOST = '0.0.0.0';



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");

});



app.use(express.static(path));

app.use("/", router);



app.listen(8080, function () {

  console.log('Example app listening on port 8080!')

})

				
			

Em seguida, vamos adicionar conteúdo estático ao aplicativo. Crie o diretório views:

				
					
mkdir views

				
			

Abra o index.html:

				
					
nano views/index.html

				
			

Adicione o código a seguir ao arquivo, que importará o Boostrap e criará um componente jumbotron com um link para a página de informações mais detalhadas do sharks.html:

				
					
[label ~/node_project/views/index.html]

<!DOCTYPE html>

<html lang="en">

   <head>

      <title>About Sharks</title>

      <meta charset="utf-8">

      <meta name="viewport" content="width=device-width, initial-scale=1">

      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

      <link href="css/styles.css" rel="stylesheet">

      <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>

      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

   </head>

   <body>

      <nav class="navbar navbar-inverse navbar-static-top">

         <div class="container">

            <div class="navbar-header">

               <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">

               <span class="sr-only">Toggle navigation</span>

               <span class="icon-bar"></span>

               <span class="icon-bar"></span>

               <span class="icon-bar"></span>

               </button>

               <a class="navbar-brand" href="#">Everything Sharks</a>

            </div>

            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

               <ul class="nav navbar-nav mr-auto">

                  <li class="active"><a href="/">Home</a></li>

                  <li><a href="/sharks">Sharks</a></li>

               </ul>

            </div>

         </div>

      </nav>

      <div class="jumbotron">

         <div class="container">

            <h1>Want to Learn About Sharks?</h1>

            <p>Are you ready to learn about sharks?</p>

            <br>

            <p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a></p>

         </div>

      </div>

      <div class="container">

         <div class="row">

            <div class="col-md-6">

               <h3>Not all sharks are alike</h3>

               <p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.</p>

            </div>

            <div class="col-md-6">

               <h3>Sharks are ancient</h3>

               <p>There is evidence to suggest that sharks lived up to 400 million years ago.</p>

            </div>

         </div>

      </div>

   </body>

</html>

				
			

Em seguida, abra um arquivo chamado sharks.html:

				
					
nano views/sharks.html

				
			

Adicione o código a seguir, o qual importa o Bootstrap e a folha de estilos personalizada e fornece informações detalhadas sobre certos tubarões:

				
					
[label ~/node_project/views/sharks.html]

<!DOCTYPE html>

<html lang="en">

   <head>

      <title>About Sharks</title>

      <meta charset="utf-8">

      <meta name="viewport" content="width=device-width, initial-scale=1">

      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

      <link href="css/styles.css" rel="stylesheet">

      <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>

      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

   </head>

   <nav class="navbar navbar-inverse navbar-static-top">

      <div class="container">

         <div class="navbar-header">

            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">

            <span class="sr-only">Toggle navigation</span>

            <span class="icon-bar"></span>

            <span class="icon-bar"></span>

            <span class="icon-bar"></span>

            </button>

            <a class="navbar-brand" href="#">Everything Sharks</a>

         </div>

         <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

            <ul class="nav navbar-nav mr-auto">

               <li><a href="/">Home</a></li>

               <li class="active"><a href="/sharks">Sharks</a></li>

            </ul>

         </div>

      </div>

   </nav>

   <div class="jumbotron text-center">

      <h1>Shark Info</h1>

   </div>

   <div class="container">

      <div class="row">

         <div class="col-md-6">

            <p>

            <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.</div>

            <img src="https://www.progressiverobot.com/images/how-to-build-a-node-js-application-with-docker-quickstart-pt-section-1.png" alt="Sawshark">

            </p>

         </div>

         <div class="col-md-6">

            <p>

            <div class="caption">Other sharks are known to be friendly and welcoming!</div>

            <img src="https://www.progressiverobot.com/images/how-to-build-a-node-js-application-with-docker-quickstart-pt-section-1.png" alt="Sammy the Shark">

            </p>

         </div>

      </div>

    </div>

   </body>

</html>

				
			

Por fim, crie a folha de estilos personalizada CSS que você vinculou ao index.html e ao sharks.html, criando primeiro uma pasta css no diretório views:

				
					
mkdir views/css

				
			

Abra a folha de estilos e adicione o código a seguir, o qual definirá a cor e a fonte desejadas para nossas páginas:

				
					
[label ~/node_project/views/css/styles.css]

.navbar {

        margin-bottom: 0;

}



body {

        background: #020A1B;

        color: #ffffff;

        font-family: 'Merriweather', sans-serif;

}

h1,

h2 {

        font-weight: bold;

}

p {

        font-size: 16px;

        color: #ffffff;

}





.jumbotron {

        background: #0048CD;

        color: white;

        text-align: center;

}

.jumbotron p {

        color: white;

        font-size: 26px;

}



.btn-primary {

        color: #fff;

        text-color: #000000;

        border-color: white;

        margin-bottom: 5px;

}



img, video, audio {

        margin-top: 20px;

        max-width: 80%;

}



div.caption: {

        float: left;

        clear: both;

}

				
			

Inicie o aplicativo:

				
					
npm start

				
			

Use seu navegador para ir para o endereço http://<^>your_server_ip<^>:8080 ou localhost:8080, caso esteja trabalhando localmente. Você verá a seguinte página de destino:

Clique no botão Get Shark Info. Você verá a seguinte página de informações:

Agora, você tem um aplicativo em funcionamento. Quando estiver pronto, saia do servidor digitando CTRL+C.

Passo 3 — Escrevendo o Dockerfile

No diretório raiz do seu projeto, crie o Dockerfile:

				
					
nano Dockerfile

				
			

Adicione o código a seguir ao arquivo:

				
					
[label ~/node_project/Dockerfile]



FROM node:&lt;^&gt;10&lt;^&gt;



RUN mkdir -p /home/node/app/node_modules &amp;&amp; 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 8080



CMD [ "npm", "start" ]

				
			

Esse Dockerfile utiliza uma imagem base alpine e garante que os arquivos do aplicativo sejam propriedade do usuário node não raiz que, por padrão, é fornecida pela Imagem Node do Docker.

Em seguida, adicione seus módulos node locais, os registros npm, o Dockerfile e o .dockerignore ao seu arquivo .dockerignore:

				
					
[label ~/node_project/.dockerignore]

node_modules

npm-debug.log

Dockerfile

.dockerignore

				
			

Compile a imagem do aplicativo usando o comando docker build:

				
					
docker build -t &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt; .

				
			

O . especifica que o contexto de compilação é o diretório atual.

Verifique suas imagens:

				
					
docker images

				
			

Você verá o seguinte resultado:

				
					
[secondary_label Output]

REPOSITORY                                         TAG                 IMAGE ID            CREATED             SIZE

&lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;          latest              1c723fb2ef12        8 seconds ago       895MB

node                                               10                  f09e7c96b6de        17 hours ago        893MB

				
			

Execute o comando a seguir para compilar um contêiner usando esta imagem:

				
					
docker run --name &lt;^&gt;nodejs-image-demo&lt;^&gt; -p &lt;^&gt;80&lt;^&gt;:8080 -d &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;

				
			

Verifique a lista dos contêineres em execução com o docker ps:

				
					
docker ps

				
			

Você verá o seguinte resultado:

				
					
[secondary_label Output]

CONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES

e50ad27074a7        &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;               "npm start"         8 seconds ago       Up 7 seconds        0.0.0.0:80-&gt;8080/tcp   nodejs-image-demo

				
			

Com seu contêiner em execução, agora você pode acessar o seu aplicativo, utilizando seu navegador para acessar o endereço http://<^>your_server_ip<^> ou o localhost. Você verá a página principal do seu aplicativo novamente:

Agora que você criou uma imagem para seu aplicativo, é possível encaminhá-la para o Docker Hub para uso futuro.

Passo 4 — Utilizando um repositório para trabalhar com imagens

O primeiro passo para enviar a imagem é fazer o login na sua conta do Docker Hub:

				
					
docker login -u &lt;^&gt;your_dockerhub_username&lt;^&gt; -p &lt;^&gt;your_dockerhub_password&lt;^&gt;

				
			

Acessando dessa maneira criará um arquivo ~/.docker/config.json no diretório home do seu usuário com as suas credenciais do Docker Hub.

Envie sua imagem com o uso do seu nome de usuário no lugar de <^>your_dockerhub_username<^>:

				
					
docker push &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;

				
			

Se quiser, teste o utilitário do registro de imagens, destruindo o contâiner e a imagem atuais de seu aplicativo e compilando-as novamente.

Primeiro, liste os contêineres em execução:

				
					
docker ps

				
			

Você verá o seguinte resultado:

				
					
[secondary_label Output]

CONTAINER ID        IMAGE                                       COMMAND             CREATED             STATUS              PORTS                  NAMES

&lt;^&gt;e50ad27074a7&lt;^&gt;        &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;   "npm start"         3 minutes ago       Up 3 minutes        0.0.0.0:80-&gt;8080/tcp   nodejs-image-demo

				
			

Usando a CONTAINER ID listada em sua saída, interrompa o contêiner do aplicativo em execução. Certifique-se de substituir a ID destacada abaixo pela seu própria CONTAINER ID:

				
					
docker stop &lt;^&gt;e50ad27074a7&lt;^&gt;

				
			

Liste todas as suas imagens com o sinalizador -a:

				
					
docker images -a

				
			

Você verá a seguinte saída com o nome da sua imagem, <^>your_dockerhub_username<^>/<^>nodejs-image-demo<^>, junto com a imagem node e as outras imagens da sua compilação:

				
					
[secondary_label Output]

REPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE

&lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;            latest              1c723fb2ef12        7 minutes ago       895MB

&lt;none&gt;                                               &lt;none&gt;              e039d1b9a6a0        7 minutes ago       895MB

&lt;none&gt;                                               &lt;none&gt;              dfa98908c5d1        7 minutes ago       895MB

&lt;none&gt;                                               &lt;none&gt;              b9a714435a86        7 minutes ago       895MB

&lt;none&gt;                                               &lt;none&gt;              51de3ed7e944        7 minutes ago       895MB

&lt;none&gt;                                               &lt;none&gt;              5228d6c3b480        7 minutes ago       895MB

&lt;none&gt;                                               &lt;none&gt;              833b622e5492        8 minutes ago       893MB

&lt;none&gt;                                               &lt;none&gt;              5c47cc4725f1        8 minutes ago       893MB

&lt;none&gt;                                               &lt;none&gt;              5386324d89fb        8 minutes ago       893MB

&lt;none&gt;                                               &lt;none&gt;              631661025e2d        8 minutes ago       893MB

node                                                 10                  f09e7c96b6de        17 hours ago        893MB

				
			

Remova o contêiner interrompido e todas as imagens, incluindo as imagens não utilizadas ou pendentes, com o seguinte comando:

				
					
docker system prune -a

				
			

Com todas as suas imagens e contêineres excluídos, agora você poderá remover a imagem do aplicativo do Docker Hub:

				
					
docker pull &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;

				
			

Liste as suas imagens novamente:

				
					
docker images

				
			

Você verá a imagem do seu aplicativo:

				
					
[secondary_label Output]

REPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE

&lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;      latest              1c723fb2ef12        11 minutes ago      895MB

				
			

Agora, é possível reconstruir seu contêiner usando o comando do Passo 3:

				
					
docker run --name &lt;^&gt;nodejs-image-demo&lt;^&gt; -p &lt;^&gt;80&lt;^&gt;:8080 -d &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;

				
			

Liste seus contêineres em execução:

				
					
docker ps

				
			
				
					
[secondary_label Output]

CONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES

f6bc2f50dff6        &lt;^&gt;your_dockerhub_username&lt;^&gt;/&lt;^&gt;nodejs-image-demo&lt;^&gt;               "npm start"         4 seconds ago       Up 3 seconds        0.0.0.0:80-&gt;8080/tcp   nodejs-image-demo

				
			

Visite novamente http://<^>your_server_ip<^> ou localhost para visualizar seu aplicativo em execução.

Tutoriais relacionados

Aqui estão os link para os guias mais detalhados relacionados a este tutorial:

Você também pode revisar a série mais extensa do artigo em De contêineres a Kubernetes com o Node.js, a partir da qual este tutorial foi adaptado.

Além disso, consulte nossa biblioteca completa dos Recursos do Docker para obter mais detalhes sobre o Docker.