Cómo crear una aplicación de Node.js con Docker [Quickstart]

Introducción

En este tutorial, se explicará la manera de crear una imagen de una aplicación para un sitio web estático que utiliza el marco Express y Bootstrap. Luego, creará un contenedor usando esa imagen, la enviará a Docker Hub y la usará para crear otro contenedor, con lo cual se demostrará la forma de recrear y escalar su aplicación.

Para acceder a una versión más detallada de este tutorial, con explicaciones más exhaustivas de cada paso, consulte Cómo crear una aplicación de Node.js con Docker.

Requisitos previos

Para este tutorial, necesitará lo siguiente:

  • Un usuario sudo en su servidor o en su entorno local.
  • Docker.
  • Node.js y npm.
  • Una cuenta de Docker Hub.

Paso 1: instalación de las dependencias de su aplicación

Primero, cree un directorio para su proyecto en el directorio principal de su usuario no root.

  • mkdir node_project

Navegue a este directorio:

  • cd node_project

Este será el directorio root del proyecto.

A continuación, cree un package.json con las dependencias de su proyecto:

  • nano package.json

Añada la siguiente información sobre el proyecto al archivo; asegúrese de sustituir la información del autor por su nombre y sus datos de contacto:

~/node_project/package.json

{   "name": "nodejs-image-demo",   "version": "1.0.0",   "description": "nodejs image demo",   "author": "Sammy the Shark <[email protected]>",   "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 las depdendencias de su proyecto:

  • npm install

Paso 2: creación de los archivos de la aplicación

Crearemos una página web que ofrece información a los usuarios sobre los tiburones.

Abra app.js en el directorio principal del proyecto para definir las rutas de este:

  • nano app.js

Añada el siguiente contenido al archivo para crear la aplicación de Express y los objetos de Router, definir el directorio base, el puerto y el host como variables, establezca las rutas y montar el middleware router junto con los activos estáticos de la aplicación:

~/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!') }) 

A continuación, añadamos algunos contenidos estáticos a la aplicación. Cree el directorio views:

  • mkdir views

Abra index.html:

  • nano views/index.html

Añada el siguiente código al archivo, que importará Bootstrap y creará un componente jumbotron con un enlace a la página de información más detallada sharks.html:

~/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> 

A continuación, abra un archivo llamado sharks.html:

  • nano views/sharks.html

Añada el siguiente código, que importa Bootstrap y la hoja de estilo personalizado, y ofrece a los usuarios información detallada sobre ciertos tiburones:

~/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://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" 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://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">             </p>          </div>       </div>     </div>    </body> </html> 

Por último, cree la hoja de estilo CSS personalizado a la que se vinculó en index.html y sharks.html creando, primero, una carpeta css en el directorio views:

  • mkdir views/css

Abra la hoja de estilo y añada el siguiente código, que establecerá el color y la fuente deseados para nuestras páginas:

~/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 la aplicación:

  • npm start

Visite en su navegador http://your_server_ip:8080 o localhost:8080 si trabaja a nivel local. Visualizará la siguiente página de destino:

Página de inicio de la aplicación

Haga clic en el botón Get Shark Info. Visualizará la siguiente página de información:

Página de información de tiburones

Ahora, tiene una aplicación lista y en funcionamiento. Cuando esté listo, salga del servidor al pulsar CTRL+C.

Paso 3: escribir el Dockerfile

En el directorio root de su proyecto, cree el Dockerfile:

  • nano Dockerfile

Añada el siguiente código al archivo:

~/node_project/Dockerfile

 FROM node:10-alpine  RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app  WORKDIR /home/node/app  COPY package*.json ./  USER node  RUN npm install  COPY --chown=node:node . .  EXPOSE 8080  CMD [ "node", "app.js" ] 

Este Dockerfile usa una imagen alpine base y garantiza que los archivos de la aplicación pertenezcan al usuario node no root proporcionado por defecto por la imagen Docker Node.

A continuación, añada sus módulos de nodo local, sus registros npm, su Dockerfile y .dockerignore a su archivo .dockerignore:

~/node_project/.dockerignore

node_modules npm-debug.log Dockerfile .dockerignore 

Compile la imagen de la aplicación usando el comando docker build:

  • docker build -t your_dockerhub_username/nodejs-image-demo .

El . especifica que el contexto de compilación es el directorio actual.

Verifique sus imágenes:

  • docker images

Verá lo siguiente:

OutputREPOSITORY                                         TAG                 IMAGE ID            CREATED             SIZE your_dockerhub_username/nodejs-image-demo          latest              1c723fb2ef12        8 seconds ago       895MB node                                               10                  f09e7c96b6de        17 hours ago        893MB 

Ejecute el siguiente comando para crear un contenedor usando esta imagen:

  • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

Inspeccione la lista de sus contenedores en ejecución con docker ps:

  • docker ps

Verá lo siguiente:

OutputCONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES e50ad27074a7        your_dockerhub_username/nodejs-image-demo               "npm start"         8 seconds ago       Up 7 seconds        0.0.0.0:80->8080/tcp   nodejs-image-demo 

Con el contenedor en ejecución, podrá visitar su aplicación dirigiéndose a la dirección http://your_server_ip o a localhost en su navegador. Visualizará la página de inicio de su aplicación una vez más:

Página de destino de la aplicación

Ahora que creó una imagen para su aplicación, puede insertarla en Docker Hub para su uso futuro.

Paso 4: utilizar un repositorio para trabajar con imágenes

El primer paso para forzar la imagen es iniciar sesión en su cuenta de Docker Hub:

  • docker login -u your_dockerhub_username -p your_dockerhub_password

Iniciar sesión de esta manera creará un archivo ~/.docker/config.json en el directorio principal de su usuario con sus credenciales de Docker Hub.

Fuerce su imagen usando su propio nombre de usuario en lugar de your_dockerhub_username:

  • docker push your_dockerhub_username/nodejs-image-demo

Si lo desea, puede probar la utilidad del registro de la imagen destruyendo el contenedor y la imagen de su aplicación actual, y volviendo a compilarlos.

Primero, enumere sus contenedores en ejecución:

  • docker ps

Verá la salida siguiente:

OutputCONTAINER ID        IMAGE                                       COMMAND             CREATED             STATUS              PORTS                  NAMES e50ad27074a7        your_dockerhub_username/nodejs-image-demo   "npm start"         3 minutes ago       Up 3 minutes        0.0.0.0:80->8080/tcp   nodejs-image-demo 

Mediante CONTAINER ID, enumerada en su salida, detenga la ejecución del contenedor de la aplicación. Asegúrese de sustituir la ID resaltada debajo por su propia CONTAINER ID:

  • docker stop e50ad27074a7

Enumere todas sus imágenes con la marca -a:

  • docker images -a

Visualizará el siguiente resultado con el nombre de su imagen, your_dockerhub_username/nodejs-image-demo, junto con la imagen node y las demás imágenes de su compilación:

OutputREPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE your_dockerhub_username/nodejs-image-demo            latest              1c723fb2ef12        7 minutes ago       895MB <none>                                               <none>              e039d1b9a6a0        7 minutes ago       895MB <none>                                               <none>              dfa98908c5d1        7 minutes ago       895MB <none>                                               <none>              b9a714435a86        7 minutes ago       895MB <none>                                               <none>              51de3ed7e944        7 minutes ago       895MB <none>                                               <none>              5228d6c3b480        7 minutes ago       895MB <none>                                               <none>              833b622e5492        8 minutes ago       893MB <none>                                               <none>              5c47cc4725f1        8 minutes ago       893MB <none>                                               <none>              5386324d89fb        8 minutes ago       893MB <none>                                               <none>              631661025e2d        8 minutes ago       893MB node                                                 10                  f09e7c96b6de        17 hours ago        893MB 

Elimine el contenedor detenido y todas las imágenes, incluso las no utilizadas o pendientes, con el siguiente comando:

  • docker system prune -a

Con todas sus imágenes y contenedores eliminados, ahora, puede extraer la imagen de la aplicación de Docker Hub:

  • docker pull your_dockerhub_username/nodejs-image-demo

Enumere sus imágenes una vez más:

  • docker images

Visualizará la imagen de su aplicación:

OutputREPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE your_dockerhub_username/nodejs-image-demo      latest              1c723fb2ef12        11 minutes ago      895MB 

Ahora, puede volver a compilar su contenedor usando el comando que se indica en el Paso 3:

  • docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

Enumere sus contenedores en ejecución:

  • docker ps
OutputCONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES f6bc2f50dff6        your_dockerhub_username/nodejs-image-demo               "npm start"         4 seconds ago       Up 3 seconds        0.0.0.0:80->8080/tcp   nodejs-image-demo 

Visite http://your_server_ip o localhost una vez más para ver su aplicación en ejecución.

Tutoriales relacionados

A continuación, se ofrecen los enlaces a más guías detalladas relacionadas con este tutorial:

  • Cómo instalar Docker Compose en Ubuntu 18.04.
  • Cómo aprovisionar y gestionar hosts remotos de Docker con Docker Machine en Ubuntu 18.04.
  • Cómo compartir datos entre contenedores de Docker.
  • Cómo compartir datos entre un contenedor y un host de Docker.

También puede consultar la serie más extensa Transición de contenedores a Kubernetes con Node.js, de cuya adaptación derivó este tutorial.

A su vez, consulte nuestra biblioteca completa de recursos de Docker para obtener más información sobre Docker.