El mundo de la integración continua fue concebido con la idea de generar artefactos de software que se pudieran compilar, es decir, que a través de un proceso de compilación resultara un archivo binario que se pudiera desplegar y correr en algún servidor. No obstante con el reciente boom de los lenguajes de scripting (lenguajes que no generan archivos binarios) este concepto se rompe un poco y los DevOps del mundo se han puesto imaginativos y a falta de un archivo binario deciden “dockerizar” las aplicaciones, entonces ahora en lugar de un archivo binario tenemos una imagen de docker que al correr sirve nuestra aplicación.

El propósito de este post es ejemplificar cómo podemos dockerizar una aplicación hecha con node.js para que posteriormente pueda ser utilizada en un proceso de integración continua o distribuida a través de un artifactory.

Tomemos como ejemplo la siguiente aplicacion sencilla:

package.json

{
  "name": "docker_web_app",
  "version": "1.0.0",
  "description": "Node.js en Docker",
  "author": "RicardoGeek",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "~4.13.3"
  }
}

server.js

'use strict';

const express = require('express');

const PORT = 8080;
const HOST = '0.0.0.0';

const app = express();
app.get('/', (req, res) => {
  res.send('Hola Docker\n');
});

app.listen(PORT, HOST);
console.log(`Aplicación corriendo en: http://${HOST}:${PORT}`);

Creando el Dockerfile

Ahora es necesario que en el mismo directorio creemos un archivo llamado Dockerfile (sin extensión) y lo abramos en nuestro editor favorito.

La primera línea de este Dockerfile sera:

FROM node

Esta es una imagen de docker disponible en el dockerhub que ya viene con node, npm y yarn listos para usarse, esta línea descarga la imagen y con las siguientes la vamos a modificar un poco para que sirva nuestra mini-aplicación, en otras palabras usamos como base la imagen de node.

En la siguiente línea definimos el WORKSPACE que es por default el directorio (dentro del S.O de la imagen) sobre el cual trabajaremos.

WORKDIR /usr/src/app

En las siguientes líneas comenzamos el proceso de instalar nuestra aplicación en la imagen base:

COPY package.json .
RUN npm install

El comando COPY copia cosas de nuestro sistema operativo al sistema operativo virtualizado, en este caso copiamos el archivo package.json al workspace antes definido. Y luego instalamos las dependencias con npm install. 

Una vez instaladas las dependencias copiamos el resto de la aplicación.

COPY . .

Y le indicamos que puerto exponer, es decir en que puerto del container debería escucharse la aplicación.

EXPOSE 8080

Y finalmente le decimos cómo correr la aplicación:

CMD [ "npm", "start" ]

Al final de todo su Dockerfile deberia verse asi:

FROM node:boron

WORKDIR /usr/src/app

COPY package.json .
RUN npm install

COPY . .

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

En el mismo directorio se debe crear un archivo .dockerignore que sirve para que el comando COPY no copie a la imagen cosas que son propias de nuestro ambiente de desarrollo local no dockerizado y para paz mental 🙂

node_modules
npm-debug.log

Construir la imagen

Ahora construir dicha imagen es tan simple como abrir una terminal, navegar al directorio de nuestra app donde esta el Dockerfile y correr el siguiente comando:

docker build -t <prefijo o usuario>/node-web-app .

al terminar su imagen debería poder ser listada con docker images.

$ docker images

# Example
REPOSITORY                      TAG        ID              CREATED
node                            node       5dfb64df5fb4    1 minute ago
<usuario>/node-web-app          latest     943ofkbdsdvv    1 minute ago

Correr la aplicacion dockerizada

Para correr la imagen corremos el siguiente comando en la terminal

docker run -p 80:8080 -d <usuario>/node-web-app

la etiqueta -p indica que el puerto 8080 del container tiene que escucharse en el puerto 80 de nuestro sistema operativo anfitrión. y la etiqueta -d indica que se corra en modo “daemon” de lo contrario tendríamos que tener la terminal abierta siempre que se quiera correr.

para probar basta con poner un curl en la terminal:

$ curl -i localhost

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 12
Date: Sun, 02 Jun 2013 03:53:22 GMT
Connection: keep-alive

Hola Docker

Ahora… manos al codigo!

Categorized in: