En este tutorial veremos como crear un servidor nodejs con docker, para ello seguiremos los pasos siguietes:
- Crear una aplicacions web con Node JS
- Crear un Dockerfile
- Construir una imagen a partir del Dockerfile
- Ejectuar la imagen como un contenedor
- Abrir nuestra aplicacion con un navegador
Crear aplicación con Node JS
Lo primer será crear el directorio donde pondremos nuestro codigo, para ello hacemos lo siguiente
mkdir simpleweb
cd simpleweb
code . (para abrir code en este directorio)
A partir de aquí trabajaremos en el terminal de visual studio code
Ahora debemos crear el fichero package.json con este contenido
{
"dependencies": {
"express": "*"
},
"scripts": {
"start": "node index.js"
}
}
Lo podéis ver en la imagen siguiente

Ahora creamos el fichero index.js con el siguiente contenido
const express = require('express');
const app = express();
app.get('/',(req,res)=>{
res.send('hola que tal!');
});
app.listen(8080,()=>{
console.log('Escuchando puerto 8080');
});
Lo podéis ver en la imagen siguiente:

Para continuar es importante que verifiquéis que estáis en el mismo directorio

Como empaquetar todo en un contendedor docker
Veamos los paso a realizar para tener una aplicación Node JS funcionando:
- Tenemos que instalar las dependencias antes de ejectuar la aplicación
- Para ello ejecutaremos npm install (asumimos que npm está instalado)
- Ejecutar un comando para poner en marcha el servidor Node JS
- El comando será npm start (asumimos que npm está instalado)
Teniendo en cuenta lo que hemos visto en tutoriales anteriores sabemos cual es la estructura de un dockerfile, solo tenemos que aplicarlo en el caso que nos ocupa
Plantilla
- Especificar una imagen base
- Instalar dependencias y programas
- Especificar un comando de inicio
Aplicación node
- FROM alpine
- RUN npm install
- CMD [«npm»,»start»]
Primero creamos el Dockerfile
#imagen base
FROM alpine
WORKDIR /usr/app
#instalamos dependencias
RUN npm install
#comando inicial
CMD ["npm","start"]

Veamos pero que pasa cuando intentamos construir esta imagen.
vemos que tenemos un error

Nos indica que el comando npm no está disponible, no tenemos ninguna copia de npm incluida en la imagen alpine que usamos
De esta forma la imagen es lo suficientemente pequeña para no tener problemas con las descargas.
Tenemos la opción de descargar las dependencias o bien ir a dockerhub y buscar una imagen que nos sirva para nuestro proposito.
En dockerhub hay una imagen oficial para nodejs

En este enlace https://hub.docker.com/_/node veremos que existe una versión de node en alpine, podemos usarla como vemos a continuación.
#imagen base
FROM node:alpine
WORKDIR /usr/app
#instalamos dependencias
RUN npm install
#comando inicial
CMD ["npm","start"]

Si ahora construímos la imagen ya no tenemos el problema de que npm no esté instalado, peró no tenemos ningun código para nuestra aplicación en nuestro contenedor y obtenemos el siguiente error:

Debemos pues de copiar el código que hemos hecho anteriormente en nuestro contenedor.
Copiar nuestro código en el contenedor
Para copiar nuestro código debemos indicarlo en nuestro Dockerfile con el comando COPY
COPY ./ ./
La primera ruta se refiere a nuestro disco local y la segunda a la imagen que estamos construyendo, para ello el Dockerfile queda como sigue
#imagen base
FROM node:alpine
WORKDIR /usr/app
#instalamos dependencias
COPY ./ ./
RUN npm install
#comando inicial
CMD ["npm","start"]
podemor ver como queda

I ahor ya no tenemos el erro anterior

Vemos que ya tenemos una id para poder arrancar nuestro contenedor, pero no la hemos etiquetado, pues lo hacemos ahora

Y ahora sí ejecutamos el contenedor

Tenemos el servidor arrancado, pero que pasa cuando vamos a visitar la web en cuestión?

No hay una correlació de puertos entre nuestra máquina donde se ejecuta docker y nuestro contenedor.
Mapeo de puertos
De alguna manera debemos indicar que cuando querramos acceder al puerto 8080 de nuestra máquina local esta petición se debe redireccionar al puerto 8080 de nuestro contenedor.
Docker no tiene ningún problema para acceder a internet, pero debemos mapear las entradas hacia nuestro contendor.
Esto lo indicamos cuando ejecutamos el contendor de la siguiente forma:
docker run -p 8080:8080 <nombre-imagen>
en nuestro caso
docker run -p 8080:8080 enguillem/simpleweb
Y ahora ya funciona nuestra aplicación node js

Una cosa a tener en cuenta es que el puerto de origen puede cambiar, el de destino no, a no ser que lo cambiemos en la aplicación.
Hacer cambios en el codigo para no hacer demasiados deploys.
Cada vez que hacemos un camibio en el codig, por ejemplo cambiamos index.js para que salga otro mensaje, no tenemos otra forma de hacer cambios que con todo un redeploy del proyecto.
Tambien sucede que cada vez que hacemos un deploy la instrucción COPY copia toda la estructura del proyecto.
Esto para proyectos grandes puede llegar a ser muy pesado.
Por tanto haremos un cambio para solo copiar lo imprescindible, que en este caso será package.json
COPY ./package.json ./
Nuestro Dockerfile quedará así

De esta forma solo se copiará este fichero cuando se realicen cambios en el.
En la línia 10 añadimos ahora un COPY ./ ./ que se encargará de copiar el resto de ficheros cuando se produzcan cambios.