¿Qué es Docker?
Docker es una plataforma de software que le permite crear, probar e implementar aplicaciones rápidamente. Docker empaqueta el software en unidades estandarizadas llamadas contenedores que tienen todo lo que el software necesita para ejecutarse, incluidas bibliotecas, herramientas del sistema, código y tiempo de ejecución. Con Docker, puede implementar y escalar rápidamente aplicaciones en cualquier entorno y saber que su código se ejecutará.
¿Como funciona docker?
En Docker tenemos imágenes que se pueden descargar automáticamente o de la página web oficial. Al ejecutar una instancia, ésta crea un Contanier, el cual vamos a aprender a utilizar. Para poder usar estos contenedores necesitamos de unos comandos que nos permiten usarlos y utilizarlos de la manera más conveniente. Esos comandos se desarrollan en una terminal, los cuales son necesarios para dar el uso adecuado a Docker. Lo primero que tenemos que entender es que las imágenes son previas, creadas por un usuario y los contenedores o containers son aplicaciones asiladas que contienen una o más imágenes. Estos contenedores contienen todo lo necesario para ejecutar una aplicación.
Docker funciona proporcionando una forma estándar de ejecutar su código. Docker es un sistema operativo para contenedores. De manera similar a cómo una máquina virtual virtualiza (elimina la necesidad de administrar directamente) el hardware del servidor, los contenedores virtualizan el sistema operativo de un servidor. Docker está instalado en cada servidor y proporciona comandos simples que puede usar para crear, iniciar o detener contenedores.
¿Qué son las imágenes en Docker?
Las imágenes son como unas plantillas ya creadas, ya sea por nosotros o por otros, sirviéndonos para crear nuestro contenedores.
Podemos almacenarlo de manera local o en un repositorio público.
Ciclo de vida de las imágenes
Las imágenes en Docker tienen un ciclo de vida útil. Este puede ser avanzado y básico.
Ciclo de vida básico
- En este ciclo de vida se crea el contenedor a partir de una imagen.
- Se ejecuta el proceso determinado en el contenedor
- El proceso de finaliza y el contenedor se detiene
- Se destruye el contenedor
Ciclo de vida avanzado
- Se crea un contenedor a partir de una imagen
- Se ejecuta un proceso en el contenedor
- Realiza acciones dentro del contenedor
- Detener el contenedor
- Lanzar el contenedor nuevamente
Comandos Docker
Creación de una imagen personalizada en Docker
- Crear aplicación NodeJS con
npm init -y
- instalar express
npm install express
- Crear
index.js
1
2
3
4
5
6
7
8
9
10
11
| const express = require("express")
const app = express()
app.get("/", (req, res) => {
res.send("<h1>Hola Mundo</h1>")
})
const port = process.env.PORT || 3000
app.listen(port, () => console.log(`Escuchando en el puerto ${port} 😎`))
|
DockerFile
1
2
3
4
5
6
7
| FROM node:18
WORKDIR /app
COPY package.json .
RUN npm install
COPY . ./
EXPOSE 3000
CMD [ "node", "index.js" ]
|
- Crear imagen con
docker build .
- Ver lista de imágenes con
docker image ls
- Borrar imagen con
docker image rm ID_IMAGEN
- Crear imagen con nombre
docker build -t docker-node-image .
- Ver lista de imágenes con
docker image ls
Ejecutar Contenedor
- Ejecutar la imagen en un contenedor
docker run -d --name node-app docker-node-image
- Ver lista de contenedores con
docker ps
- Escribir en el navegador http://localhost:3000/ la aplicación no funcionara ya que no se ha especificado puerto
- Eliminar contenedor con
docker rm node-app -f
- Ejecutar la imagen con puerto con
docker run -p 3000:3000 -d --name node-app docker-node-image
- 3000:3000 el numero de la izquierda representa el puerto desde el cual hay trafico de entrada, el de la derecha el puerto donde docker o la aplicación esta escuchando
- Para ver el sistema de archivos del contenedor entramos en modo interactivo con
docker exec -it node-app bash
- Listar los archivos con
ls
salir con exit
- Eliminar contenedor
DockerIgnore
- Crear archivo
.dockerignore
1
2
3
4
5
| node_modules
dockerfile
.dockerignore
.git
.gitignore
|
- Reconstruir imagen
docker build -t docker-node-image .
- Ejecutar contenedor
docker run -p 3000:3000 -d --name node-app docker-node-image
- Revisar contendor y verificar archivos
Integración de imagen para desarrollo
- Realizar cambios a etiqueta H1 en
index.js
- Verificar que no hay cambios en la imagen con
docker exec -it node-app bash
y luego con cat index.js
Un montaje de enlace (mount bind) es otro tipo de montaje, que le permite compartir un directorio desde el sistema de archivos del host en el contenedor. Al trabajar en una aplicación, puede usar un montaje de vinculación para montar el código fuente en el contenedor. El contenedor ve los cambios que realiza en el código inmediatamente, tan pronto como guarda un archivo. Esto significa que puede ejecutar procesos en el contenedor que observen cambios en el sistema de archivos y respondan a ellos.
- Usando un Mount Bind para sincronizar los archivos al contendor
docker run -v ${pwd}:/app -p 3000:3000 -d --name node-app docker-node-image
en powershell - CMD
docker run -v %cd%:/app -p 3000:3000 -d --name node-app docker-node-image
- Linux y MacOS
docker run -v $(pwd):/app -p 3000:3000 -d --name node-app docker-node-image
- Modificar
index.js
y verificar que el contenido se actualiza dentro el contenedor - Instalar nodemon como dependencia dev
npm install nodemon --save-dev
- Modificar
package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| {
"name": "docker-node",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon -L index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^2.0.21"
}
}
|
1
2
3
4
5
6
7
| FROM node:18
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "npm", "run", "dev" ]
|
Logs de contenedores
- Borrar carpeta
node_modules
- Utilizar
docker ps -a
para mostrar los contendores ejecutados - Usar
docker logs NOMBRE_CONTENEDOR
para ver logs del contenedor - Evitar que el bind mount sobreescriba la carpeta
node_modules
del contenedor con docker run -v ${pwd}:/app -v /app/node_modules -p 3000:3000 -d --name node-app docker-node-image
- Entrar al contenedor con
docker exec -it node-app bash
- Crear archivo dentro dl contenedor con
touch nombre_archivo
- Para que el directorio del contenedor sea solo de lectura
docker run -v ${pwd}:/app:ro -v /app/node_modules -p 3000:3000 -d --name node-app docker-node-image
Variables de entorno
1
2
3
4
5
6
7
8
| FROM node:18
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
ENV PORT 3000
EXPOSE $PORT
CMD [ "npm", "run", "dev" ]
|
- Reconstruir imagen
docker build -t docker-node-image .
- Ejecutar contenedor con
docker run -v ${pwd}:/app:ro -v /app/node_modules --env PORT=4000 -p 3000:4000 -d --name node-app docker-node-image
- Entrar al contenedor con
docker exec -it node-app bash
- Imprimir variables de entorno con
printenv
- Crear archivo
.env
- Eliminar contenedor con
docker rm node-app -f
- Eliminar imagen
docker image rm docker-node-image
- Reconstruir imagen
docker build -t docker-node-image .
- Ejecutar contenedor con
docker run -v ${pwd}:/app:ro -v /app/node_modules --env-file ./.env PORT=4000 -p 3000:4000 -d --name node-app docker-node-image
Borrar Volúmenes
- Verificar volúmenes con
docker volumen ls
- Eliminar con
docker volume ID_VOLUMEN
o docker volume prune
- Eliminar contenedor y volumen con
docker rm node-app -fv
Docker compose
- Crear archivo
docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
| version: '3.8'
services:
node-app:
build: .
ports:
- "3000:3000"
volumes:
- ./:/app:ro
- /app/node_modules
environment:
- PORT=3000
#env_file:
#- ./.env
|
- Ejecutar
docker-compose up -d
- Para detener
docker-compose down -v
- Comando para forzar la reconstrucción de imagen al usar compose
docker-compose up -d --build
Multiple Compose
1
2
3
4
5
6
7
8
| FROM node:18
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
ENV PORT 3000
EXPOSE $PORT
CMD [ "node", "index.js" ]
|
- Modificar
docker-compose.yml
1
2
3
4
5
6
7
8
| version: '3.8'
services:
node-app:
build: .
ports:
- "3000:3000"
environment:
- PORT=3000
|
- Crear
docker-compose-dev.yml
1
2
3
4
5
6
7
8
9
10
| version: '3.8'
services:
node-app:
build: .
volumes:
- ./:/app
- /app/node_modules
environment:
- NODE_ENV=development
command: npm run dev
|
- Crear
docker-compose-prod.yml
1
2
3
4
5
6
| version: '3.8'
services:
node-app:
environment:
- NODE_ENV=production
command: node index.js
|
- Ejecutar dev mode con
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build
- Para detener
docker-compose down -v
- Ejecutar prod mode con
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
- Para detener
docker-compose -f docker-compose.yml -f docker-compose.prod.yml down -v
- Actualizar
.dockerignore
1
2
3
4
5
| node_modules
Dockerfile
.git
.gitignore
docker-compose*
|