Docker nos permite definir dentro de una máquina todos los parámetros del entorno que utilizaremos para desplegar nuestra aplicación (versión del servidor Java, versión de Node…)
Docker crea un entorno que utiliza el sistema operativo de la máquina donde es utilizado, en lugar de crear una máquina virtual utilizando un sistema operativo independiente (usando Virtual Box, por ejemplo).
Por un lado, esto nos simplificará la configuración del entorno de desarrollo dentro de nuestro ordenador y nos facilitará la migración de nuestro entorno a otros sistemas como AWS, etc.
Pasos para la ejecución
Paso 1. Instalación de Docker Desktop.
1. Instalamos la versión Desktop de Docker.
Para un entorno de node:
3. Creamos en la raíz de nuestro proyecto un fichero llamado Dockerfile con el siguiente código:
# Instalar NodeJS en el contenedor de Docker
# El comando FROM instala una imagen oficial
FROM node:16.16.0-alpine
# Establecer la carpeta de trabajo dentro del ecosistema de Docker
WORKDIR /app
# Copiar todo el código de nuestra aplicación en el contenedor de Docker
COPY . ./
RUN npm i
EXPOSE 3000
# start app
CMD ["npm", "start"]
Para un entorno de springboot:
Necesitamos tener maven instalado en el sistema operativo. Lo descargamos y añadimos la carpeta de binarios al path de las variables de entorno de nuestro sistema operativo.
Debemos asegurarnos de que la siguiente línea forma parte de nuestro pom.xml:
<packaging>war</packaging>
El siguiente comando creará un empaquetado war dentro de la carpeta target.
mvn clean package -DskipTests
Podemos comprobar que el empaquetado se ha generado correctamente ejecutándolo:
java -jar target/[nombreEmpaquetado].war
Creamos en la raíz de nuestro proyecto un fichero llamado Dockerfile con el siguiente código:
FROM openjdk:8-alpine
ADD target/prueba-0.0.1-SNAPSHOT.war /usr/share/app.war
ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/app.war"]
Paso 3. Build de la imagen
4. Creamos la imagen ejecutando el siguiente comando en la raíz de la carpeta de nuestro proyecto:
docker build . -t=nombre-proyecto-docker
5. Ejecutamos nuestra imagen. Para ello, crearemos un contenendor:
docker run -p 3010:3000 --name nombre-contenedor nombre-proyecto-docker
Al crear la imagen hemos especificado:
- el puerto de nuestro ordenador (3010) asociado al puerto interno del contenedor (3000). Para un proyecto de springboot pondríamos 8080:8080.
- El nombre del contenedor.
- El nombre de la imagen que queremos ejecutar.
Si quisieramos realizar estos pasos utilizando Docker Desktop, hubieramos pulsado aquí:
![Curso de Docker 1 Curso de Docker 1](https://pablomonteserin.com/wp-content/uploads/2022/12/image-3-1024x354.png)
![Curso de Docker 2 Curso de Docker 2](https://pablomonteserin.com/wp-content/uploads/2022/12/image-2-895x1024.png)
6. Para probar la aplicación iremos a localhost: 3010.
![Curso de Docker 3 Curso de Docker 3](https://pablomonteserin.com/wp-content/uploads/2022/12/image-1.png)
Docker Compose
Nos va a permitir, con un solo comando del package.json:
- Crear una imagen a partir de nuestro proyecto.
- Configurar dicha imagen
- Ejecutarla en un contenedor.
Debemos crear el siguiente fichero en nuestro proyecto. Lo he creado en la raíz, pero podría estar en otro sitio.
docker-compose.yml
version: "3.8" # Versión de sintaxis del propio fichero docker-compose.yml
services:
app-dev:
container_name: container-name
build:
context: . # Ruta en la que se encuentra el Dockerfile
ports:
- 3002:3000
Añadimos el siguiente comando a los scripts del package.json:
"dev": "docker-compose up --build app-dev",
Volúmenes
Nos permiten vincular un directorio externo al contenedor con uno interno.
app-dev:
container_name: container-name
build:
context: . # Ruta en la que se encuentra el Dockerfile
volumes:
- ./src:/app/src
ports:
- 3002:3000
Configuración para producción
Dockerfile
FROM node:16.16.0-alpine as installer
WORKDIR /app
COPY . ./
RUN npm i
FROM installer as builder
RUN npm run build
FROM installer as development
EXPOSE 3000
CMD ["npm", "start"]
FROM nginx:1.21.0-alpine AS production
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml
version: "3.8" # Versión de sintaxis del propio fichero docker-compose.yml
services:
app-dev:
container_name: container-name
build:
context: . # Ruta en la que se encuentra el Dockerfile
target: development
volumes:
- ./src:/app/src
ports:
- 3000:3000
app-pro:
container_name: container-name-pro
build:
context: . # Ruta en la que se encuentra el Dockerfile
target: production
ports:
- 3001:80
package.json:
"scripts": {
"dev": "docker-compose up --build app-dev",
"pro": "docker-compose up --build app-pro",
"clean-docker": "docker-compose down && docker-compose down --volumes",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
Configuración para routing
Debemos subir una especie de .htacces en apache, pero para ngix.
ngix.cond
server {
listen 80;
location / {
root /usr/share/nginx/html/;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
}
Dockerfile
...
FROM nginx:1.21.0-alpine AS production
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]