Implementación de una aplicación Node.js en un droplet de DigitalOcean con Docker

Hay muchos servicios de alojamiento basados ​​en la nube en línea. En este artículo, crearemos una aplicación Node.js, la dockerizaremos y la implementaremos en un Droplet de DigitalOcean para ponerla en funcionamiento en línea.

Introducción

JavaScript ha recorrido un largo camino a lo largo de los años y ahora estamos en un punto en el que puede escribir e implementar una aplicación web con mucha facilidad. Frameworks como Expresar, Paño y Meteorito solo han hecho esto más fácil.

Seguir la mayoría de los tutoriales en Internet significa que estará trabajando en su máquina local con un proyecto local. Pero, ¿y si nos gustaría compartir el proyecto con el mundo o con nuestros amigos? Hoy vamos a ver cómo implementar una aplicación Node.js en una Gota de océano digital, para que cualquiera en Internet pueda interactuar con él.

Requisitos previos

ventana acoplable

Usaremos Estibador para contener nuestra aplicación en una unidad pequeña y fácil de implementar. Esta unidad se puede implementar en cualquier lugar donde esté instalado Docker.

Crea una cuenta con Centro acoplable, y descarga la edición community/desktop. ¡Usaremos esta cuenta más tarde!

Océano Digital

océano digital es un servicio de hospedaje pago: usaremos su servicio de $5 al mes y podemos apagarlo tan pronto como terminemos minimice los costos, pero necesitará un método de pago para dárselo a DigitalOcean antes de usarlo.

Aplicación de nodo

Para esto, vamos a crear una aplicación Express simple que sirva un punto de conexión de estado para que nosotros lo presionemos y descubramos si nuestra aplicación se está ejecutando. En la línea de comando, vamos a crear un directorio:

1
$ mkdir digital-ocean

Y luego muévase al directorio e inicialice nuestra aplicación:

1
2
$ cd digital-ocean
$ npm init

Siéntase libre de presionar ENTER para omitir/establecer las respuestas predeterminadas para todas las siguientes preguntas, o agregar nombres/descripciones de paquetes si lo desea.

Para los propósitos de este tutorial, asumiremos que "punto de entrada" se deja como index.js. Deberías terminar con algo que se vea así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package name: (digital-ocean)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)

{
  "name": "digital-ocean",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes)

Si miras en el directorio ahora (ls en la línea de comando), verás un archivo solitario package.json. Esto contiene la configuración de nuestra aplicación. Saltemos allí y agreguemos una línea al bloque "scripts":

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "name": "digital-ocean",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Esto nos permite iniciar nuestra aplicación ejecutando npm start. Los scripts son muy útiles para configurar tareas que realizará con frecuencia con una aplicación, como pruebas o varios procesos de compilación.

A continuación, queremos instalar Express:

1
$ npm install express

Y finalmente, escribamos el código que servirá a nuestro punto final /status. En el mismo directorio que nuestro archivo package.json, cree un archivo llamado index.js:

1
2
3
4
5
6
7
const express = require('express')
const app = express()
const port = 3000

app.get('/status', (req, res) => res.send({status: "I'm alive!"}))

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

Finalmente, probemos nuestra aplicación ejecutando:

1
$ npm start

Al abrir un navegador web y navegar a http://localhost:3000/status, debería recibir algo como esto:

1
{"status":"I'm alive!"}

Ahora tenemos una aplicación Express en funcionamiento, que ahora podemos agrupar e implementar utilizando Docker y un servidor Droplet.

Dockerización de una aplicación Node.js

Ahora tenemos una aplicación que funciona, pero queremos poder implementarla. Podríamos crear un servidor y luego configurarlo para que tenga exactamente la misma configuración que nuestra máquina actual, pero eso puede ser complicado. En cambio, empaquetémoslo usando Docker.

Cómo funciona Docker

Docker nos permite definir un conjunto de instrucciones que crean lo que llamamos capas. Si quiere imaginar cómo se ve una capa, imagine su sistema de archivos congelado en un momento en el tiempo. Cada nueva capa es una modificación o adición a ese sistema de archivos, que luego se vuelve a congelar.

Estas composiciones de capas superpuestas forman lo que se conoce como imagen, que es esencialmente un sistema de archivos en una caja, listo para usar.

Esta imagen se puede usar para crear contenedores, que son versiones vivas de ese sistema de archivos, listos para ejecutar una tarea que definamos para él.

Otro aspecto útil de esto es que podemos usar imágenes prefabricadas como la primera capa en nuestras propias imágenes, lo que nos da un empujón al evitar configuraciones repetitivas.

Creación de una imagen de Docker

Lo primero que queremos hacer es crear un Dockerfile. Este archivo es un conjunto de instrucciones que Docker debe interpretar para comprender exactamente cómo empaquetar su aplicación como una imagen.

En la carpeta de su proyecto, cree un archivo llamado Dockerfile y luego ingrese estos comandos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
FROM node:13-alpine

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000
CMD [ "npm", "start" ]

Aquí hay algunos componentes, repasemos línea por línea:

  • FROM node:10: le dice a Docker que use otra imagen como capa base en nuestro Dockerfile; en este caso, obtenemos una imagen con Node.js instalado, versión 10.

  • WORKDIR /usr/src/app: le dice a Docker la carpeta en la que debería ejecutar los siguientes comandos.

  • COPY package*.json ./: le dice a Docker que copie solo package.json y package-lock.json en la imagen de Docker. Hacemos esto porque Docker puede cachear composiciones de capas, lo que significa que si nada cambia en nuestro package.json, podemos extraer una composición de capas que ya hemos creado antes.

  • EJECUTAR npm install: hace lo que dice en la lata y ejecuta el comando npm install para crear una nueva capa de la imagen con todos nuestros módulos instalados. De nuevo, si nada ha cambiado en nuestro package.json, se extraerá una versión preconstruida.

  • COPIA. .: copia el resto de la aplicación en el sistema de archivos. Como es probable que la aplicación cambie con más frecuencia (es decir, cada vez que realice un cambio de código), tiene sentido hacer de esta una de las últimas capas con fines de almacenamiento en caché.

  • EXPOSE 3000: le dice a Docker que abra el puerto 3000 en el contenedor cuando se está ejecutando.

  • CMD [ "npm", "start" ]: ejecuta npm start al instanciar el contenedor y ejecuta nuestra aplicación dentro de él.

Ejecutando nuestra Docker Build

Ahora que tenemos nuestras instrucciones escritas, ¡construyamos nuestra imagen! En el mismo directorio que su Dockerfile, ejecute:

1
$ docker build . -t digital-ocean-app

Esto crea una imagen y luego le da un nombre específico o 'etiqueta'; en este caso, es digital-ocean-app. Para probar que nuestra aplicación funciona, ejecútela localmente con:

1
$ docker run -p 3000:3000 digital-ocean-app

Esto ejecutará nuestra imagen de Docker como un contenedor y ejecutará la parte CMD de nuestro Dockerfile.

La sección -p 3000:3000 hace lo que se conoce como mapeo de puertos. El número antes de los dos puntos es el puerto en nuestra máquina local que queremos mapear, y el número después es el puerto dentro del contenedor al que queremos enrutar.

Esto significa que el puerto 3000 en nuestra máquina ahora se conectará al puerto 3000 en el contenedor Docker en el que se ejecuta nuestra aplicación.

Para probar esto, abra su navegador y navegue de regreso a http://localhost:3000/status y debería ver su punto final de estado.

Publicación de la imagen en Docker Hub

Ahora que tenemos nuestra imagen de Docker empaquetada, debemos almacenarla en algún lugar desde donde podamos volver a bajarla. Deberá volver a iniciar sesión en Centro acoplable y luego hacer clic en 'Crear repositorio'. Al igual que los repositorios de Git nos permiten almacenar nuestros proyectos de Git controlados por versión, los repositorios de Docker nos permiten almacenar nuestras imágenes de Docker.

Deberá completar el nombre del repositorio, así como una descripción opcional y si es o no un repositorio público o privado (si necesita o no iniciar sesión como un usuario autorizado de Docker, básicamente ).

Por ahora, déjelo en público, ya que nos facilitará la vida cuando intentemos implementarlo en DigitalOcean. Finalmente, desplácese hasta la parte inferior y presione 'Crear'.

Volviendo a la línea de comandos, necesitamos etiquetar nuestra imagen antes de enviarla:

1
$ docker tag digital-ocean-app <USER_NAME>/digital-ocean-app

Tendremos que reemplazar la sección <USER_NAME> con nuestro nombre de usuario de Docker Hub. Opcionalmente, si queremos especificar que estamos enviando una versión específica de nuestra imagen, podemos hacer lo siguiente:

1
$ docker tag digital-ocean-app <USER_NAME>/digital-ocean-app:<VERSION>

La <VERSION> se llama 'etiqueta de imagen'; podríamos poner un número allí (1.0, 1.1, etc.) para representar lanzamientos, o incluso describir un entorno (dev, staging , prod). Tiendo a usar el hash de confirmación de Git para saber exactamente lo que estoy ejecutando y poder compararlo con mi historial de confirmación.

De forma predeterminada, cada vez que presione, su repositorio creará automáticamente una imagen con la etiqueta : más reciente, por lo que siempre sabemos cuál es la etiqueta de la imagen enviada más recientemente.

Para poder empujar a nuestro repositorio, necesitaremos iniciar sesión:

1
$ docker login

Ingrese sus credenciales de Docker Hub.

Una vez que haya iniciado sesión correctamente, podrá enviar su imagen con:

1
$ docker push <USER_NAME>/digital-ocean-app:<OPTIONAL_VERSION>

Océano digital {# océano digital}

Finalmente, podemos implementar nuestra aplicación dockerizada en DigitalOcean. Primero, vamos a crear una cuenta:

create digital ocean account

Deberá proporcionar algunos datos personales, incluidos los detalles de pago, así como configurar un proyecto inicial. Siéntase libre de darle un nombre, pero si planea hacer algo extenso, seleccione algunas de las opciones para optimizar su configuración.

Una vez que haya terminado, será redirigido a la página raíz de su proyecto. En el lado izquierdo hay una barra de herramientas con varias opciones. Siéntase libre de explorar: DigitalOcean es bueno para informarle si algo que está a punto de hacer le costará.

root page of digital ocean project

Creación de una clave SSH

Antes de hacer nada, necesitaremos crear una clave SSH y subir la parte pública a DigitalOcean. Las claves SSH vienen en dos partes, una clave pública y una clave privada.

Una clave privada se utiliza para autenticar a un usuario en un sistema. El sistema hace esto realizando una función usando la clave pública para verificar que la clave privada es la que se usa para generar la clave pública. Si es así, ambos provienen del mismo lugar, por lo que se puede confiar en el usuario.

DigitalOcean querrá una clave pública que pueda colocar en cualquier Droplet que iniciemos, para que podamos acceder a ellos con una clave que sabemos que solo nosotros tenemos.

Vamos a crear un par de claves SSH ahora:

1
$ ssh-keygen -t rsa -b 4096

Este comando debería funcionar en Windows, Linux y MacOS.

Esto le pedirá un archivo en el que desea guardar la clave que puede llamar algo como “clave de océano digital”.

También le pedirá una frase de contraseña; siéntase libre de establecer una si lo desea o puede dejarla vacía. Si lo creó en la misma carpeta en la que hemos estado trabajando, verá dos archivos, uno llamado digital-ocean-key y otro llamado digital-ocean-key.pub, estos son respectivamente sus claves privadas y públicas.

Adición de la clave SSH a su cuenta de DigitalOcean

En su cuenta de DigitalOcean, en la parte inferior izquierda, hay un enlace para 'Seguridad'. Siga este enlace y la página siguiente tendrá una opción para agregar una clave SSH:

digital ocean security ssh key

Haga clic en 'Agregar una clave SSH' y aparecerá un cuadro de diálogo para ingresar su clave. Simplemente copie el contenido de su digital-ocean-key.pub en el cuadro de texto grande (puede imprimir el contenido en la terminal con cat digital-ocean-key.pub).

entering ssh key

En el cuadro más pequeño debajo de él, asigne un nombre a esa clave.

Configuración de una gota de DigitalOcean

Una vez que haya agregado su clave SSH. haga clic en el enlace 'Gotas' a la izquierda y luego, en la página siguiente, haga clic en 'Crear gota'.

creating digital ocean droplet

En DigitalOcean, un Droplet es un servidor virtual privado que puede configurarse y usarse fácilmente para ejecutar sus aplicaciones.

En esta página, se le presentarán varias opciones para configurar su Droplet de DigitalOcean, incluida la distribución, el plan, el tamaño/costo por mes, la región y la autenticación.

En lugar de seleccionar una distribución y configurarla nosotros mismos, vamos a hacer que DigitalOcean cree un Droplet que ya tiene Docker ejecutándose por nosotros.

Haga clic en 'Marketplace' sobre las diversas distribuciones de Linux; aquí es donde puede encontrar varias configuraciones existentes; estos son Droplets que, cuando se inician, comenzarán con el software descrito ya instalado.

Esto es un ahorro de tiempo real y significa que podemos iniciar varias instancias con exactamente la misma configuración si quisiéramos, en lugar de tener que configurarlas todas individualmente.

Debería haber una opción para un Docker Droplet. De lo contrario, haga clic en 'Ver todas las aplicaciones de Marketplace', y podrá encontrar una configuración adecuada de Docker allí:

En 'Plan', queremos seleccionar 'Standard'. Seleccionemos la opción $5 al mes, para propósitos de demostración.

selecting digital ocean monthly plan

Siéntase libre de elegir la región que sea adecuada para usted; generalmente, la más cercana será la más fácil de acceder, pero no debería tener un impacto masivo.

En Autenticación, seleccione 'SSH Key' y seleccione las claves que le gustaría usar (como la que creó en el último paso). También puede nombrar su Droplet si lo desea. Cuando termines, haz clic en 'Crear Droplet' en la parte inferior.

Espere un minuto para que su Droplet se inicie. Aparecerá debajo del panel 'Gotas' con un punto verde al lado cuando esté listo. En este punto, estamos listos para conectarnos.

Ejecución de imágenes de Docker en gotas DO

Haga clic en el Droplet iniciado y verá los detalles al respecto. Por el momento, estamos interesados ​​en la dirección IP: esta es la dirección en la que se encuentra el Droplet en Internet.

Para acceder a él, necesitaremos conectarnos usando nuestra clave privada creada previamente. Desde la misma carpeta que esa clave privada, ejecute:

1
$ ssh -i digital-ocean-key [correo electrónico protegido]<IP_ADDRESS>

-i digital-ocean-key especifica que estás usando una clave SSH y dónde se encuentra esa clave. El [correo electrónico protegido]<IP_ADDRESS> especifica el usuario y la dirección a la que intenta conectarse; en este caso, el usuario con el que intentamos conectarnos es root y la dirección IP sería la dirección del DigitalOcean Droplet.

Una vez que esté conectado a la instancia, es solo cuestión de ejecutar su imagen de Docker. Si lo dejó en un repositorio público, puede ejecutarlo fácilmente con el mismo nombre que usó para enviarlo:

1
$ docker run -p 3000:3000 <DOCKER_USER_NAME>/digital-ocean-app:<OPTIONAL_TAG>

Si lo coloca en un repositorio privado, deberá iniciar sesión con docker login nuevamente antes de ejecutar su comando docker run.

Una vez que su contenedor Docker se esté ejecutando, abra una pestaña en su navegador y navegue hasta <IP_ADDRESS>:3000/status - donde <IP_ADDRESS> es la dirección IP del Droplet de DigitalOcean en el que está ejecutando el contenedor .

Se le debe presentar su punto final de estado creado anteriormente. ¡Felicitaciones! ¡Ahora tiene una aplicación Node.js ejecutándose en DigitalOcean!

Conclusión

Hay algunas direcciones a las que puede ir desde aquí. Primero, probablemente querrá desarrollar su aplicación para que haga cosas más útiles.

Es posible que desee comprar un dominio para alojar su aplicación y apuntarlo a su Droplet de DigitalOcean para que sea más fácil de acceder.

También recomendaría explorar algunas de las demás capacidades de DigitalOcean: podría usar algunas de sus herramientas de red para asegurar su Droplet al restringir el acceso al puerto SSH (22), explorar algunas de las otras imágenes que tiene Docker, ¡o incluso busque crear bases de datos para su aplicación!