Contenedoriza una aplicación de Java
Requisitos previos
- Has instalado la versión más reciente de Docker Desktop. Docker agrega nuevas características regularmente y algunas partes de esta guía pueden funcionar solo con la versión más reciente de Docker Desktop.
- Tienes un cliente de Git. Los ejemplos de esta sección utilizan un cliente de Git basado en línea de comandos, pero puedes usar cualquier cliente.
Resumen
Esta sección te guía a través de la contenedorización y ejecución de una aplicación de Java.
Obtén la aplicación de ejemplo
Clona la aplicación de ejemplo que utilizarás en tu máquina de desarrollo local. Ejecuta el siguiente comando en una terminal para clonar el repositorio.
$ git clone https://github.com/spring-projects/spring-petclinic.git
La aplicación de ejemplo es una aplicación Spring Boot construida con Maven. Para obtener más detalles, consulta el archivo readme.md en el repositorio.
Inicializa los activos de Docker
Ahora que tienes una aplicación, puedes crear los activos de Docker necesarios para contenedorizarla. Puedes utilizar la función integrada Docker Init de Docker Desktop para ayudar a agilizar el proceso, o puedes crear los activos manualmente.
Dentro del directorio spring-petclinic, ejecuta el comando docker init. docker init proporciona una configuración predeterminada, pero deberás responder algunas preguntas sobre tu aplicación. Consulta el siguiente ejemplo para responder a las preguntas de docker init y utiliza las mismas respuestas para tus indicaciones.
La aplicación de ejemplo ya contiene activos de Docker. Se te preguntará si deseas sobrescribir los activos de Docker existentes. Para continuar con esta guía, selecciona y para sobrescribirlos.
$ docker init
Welcome to the Docker Init CLI!
This utility will walk you through creating the following files with sensible defaults for your project:
- .dockerignore
- Dockerfile
- compose.yaml
- README.Docker.md
Let's get started!
WARNING: The following Docker files already exist in this directory:
- docker-compose.yml
? Do you want to overwrite them? Yes
? What application platform does your project use? Java
? What's the relative directory (with a leading .) for your app? ./src
? What version of Java do you want to use? 21
? What port does your server listen on? 8080
En el ejemplo anterior, observa la advertencia (WARNING). docker-compose.yaml ya existe, por lo que docker init sobrescribe ese archivo en lugar de crear un nuevo archivo compose.yaml. Esto evita tener múltiples archivos de Compose en el directorio. Ambos nombres son compatibles, pero Compose prefiere el nombre canónico compose.yaml.
Si no tienes Docker Desktop instalado o prefieres crear los activos manualmente, puedes crear los siguientes archivos en el directorio de tu proyecto.
Crea un archivo llamado Dockerfile con el siguiente contenido.
# syntax=docker/dockerfile:1
# Se proporcionan comentarios a lo largo de este archivo para ayudarte a empezar.
# Si necesitas más ayuda, visita la guía de referencia de Dockerfile en
# https://docs-docker.esdocu.com/go/dockerfile-reference/
# ¿Quieres ayudarnos a mejorar esta plantilla? Comparte tus comentarios aquí: https://forms.gle/ybq9Krt8jtBL3iCk7
################################################################################
# Crea una etapa para resolver y descargar dependencias.
FROM eclipse-temurin:21-jdk-jammy as deps
WORKDIR /build
# Copia el wrapper mvnw con permisos de ejecución.
COPY --chmod=0755 mvnw mvnw
COPY .mvn/ .mvn/
# Descarga las dependencias como un paso separado para aprovechar la caché de Docker.
# Utiliza un montaje de caché en /root/.m2 para que las compilaciones posteriores no tengan que
# volver a descargar los paquetes.
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
--mount=type=cache,target=/root/.m2 ./mvnw dependency:go-offline -DskipTests
################################################################################
# Crea una etapa para compilar la aplicación basada en la etapa con las dependencias descargadas.
# Este Dockerfile está optimizado para aplicaciones Java que generan un "uber jar", el cual incluye
# todas las dependencias necesarias para ejecutar tu aplicación dentro de una JVM. Si tu aplicación no genera
# un "uber jar" y en su lugar depende de un servidor de aplicaciones como Apache Tomcat, deberás actualizar esta
# etapa con el nombre de archivo correcto de tu paquete y actualizar la imagen base de la etapa "final"
# para usar el servidor de aplicaciones correspondiente, por ejemplo, usando tomcat (https://hub.docker.com/_/tomcat/) como imagen base.
FROM deps as package
WORKDIR /build
COPY ./src src/
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
--mount=type=cache,target=/root/.m2 \
./mvnw package -DskipTests && \
mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar
################################################################################
# Crea una etapa para extraer la aplicación en capas separadas.
# Aprovecha las herramientas de capas de Spring Boot y la caché de Docker extrayendo
# la aplicación empaquetada en capas separadas que se pueden copiar en la etapa final.
# Consulta la documentación de Spring como referencia:
# https://docs.spring.io/spring-boot/docs/current/reference/html/container-images.html
FROM package as extract
WORKDIR /build
RUN java -Djarmode=layertools -jar target/app.jar extract --destination target/extracted
################################################################################
# Crea una nueva etapa para ejecutar la aplicación que contenga las dependencias mínimas
# de tiempo de ejecución para la aplicación. Esto a menudo utiliza una imagen base diferente
# de la etapa de instalación o compilación desde la cual se copian los archivos necesarios.
#
# El siguiente ejemplo utiliza la imagen JRE de eclipse-temurin como base para ejecutar la aplicación.
# Al especificar la etiqueta "21-jre-jammy", también utilizará la versión más reciente
# de esa etiqueta cuando construyas tu Dockerfile.
# Si la reproducibilidad es importante, considera usar un SHA de digest específico, como
# eclipse-temurin@sha256:99cede493dfd88720b610eb8077c8688d3cca50003d76d1d539b0efc8cca72b4.
FROM eclipse-temurin:21-jre-jammy AS final
# Crea un usuario no privilegiado bajo el cual se ejecutará la aplicación.
# Consulta https://docs-docker.esdocu.com/go/dockerfile-user-best-practices/
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser
# Copia el ejecutable desde la etapa "extract".
COPY --from=extract build/target/extracted/dependencies/ ./
COPY --from=extract build/target/extracted/spring-boot-loader/ ./
COPY --from=extract build/target/extracted/snapshot-dependencies/ ./
COPY --from=extract build/target/extracted/application/ ./
EXPOSE 8080
ENTRYPOINT [ "java", "org.springframework.boot.loader.launch.JarLauncher" ]El ejemplo ya contiene un archivo de Compose. Sobrescribe este archivo para seguir la guía. Actualiza el archivo docker-compose.yaml con el siguiente contenido.
# Se proporcionan comentarios a lo largo de este archivo para ayudarte a empezar.
# Si necesitas más ayuda, visita la guía de referencia de Docker Compose en
# https://docs-docker.esdocu.com/go/compose-spec-reference/
# Aquí las instrucciones definen tu aplicación como un servicio llamado "server".
# Este servicio se construye a partir del Dockerfile en el directorio actual.
# Puedes agregar otros servicios de los que tu aplicación pueda depender aquí, como una
# base de datos o una caché. Para ver ejemplos, consulta el repositorio Awesome Compose:
# https://github.com/docker/awesome-compose
services:
server:
build:
context: .
ports:
- 8080:8080
# La sección comentada a continuación es un ejemplo de cómo definir una base de datos
# PostgreSQL que tu aplicación puede utilizar. `depends_on` le indica a Docker Compose que
# inicie la base de datos antes que tu aplicación. El volumen `db-data` persiste los
# datos de la base de datos entre reinicios del contenedor. El secreto `db-password` se utiliza
# para establecer la contraseña de la base de datos. Debes crear `db/password.txt` y agregar
# la contraseña que elijas antes de ejecutar `docker compose up`.
# depends_on:
# db:
# condition: service_healthy
# db:
# image: postgres:18
# restart: always
# user: postgres
# secrets:
# - db-password
# volumes:
# - db-data:/var/lib/postgresql
# environment:
# - POSTGRES_DB=example
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
# expose:
# - 5432
# healthcheck:
# test: [ "CMD", "pg_isready" ]
# interval: 10s
# timeout: 5s
# retries: 5
# volumes:
# db-data:
# secrets:
# db-password:
# file: db/password.txtCrea un archivo llamado .dockerignore con el siguiente contenido.
# Incluye aquí cualquier archivo o directorio que no quieras que se copie a tu
# contenedor (por ejemplo, artefactos de compilación local, archivos temporales, etc.).
#
# Para obtener más ayuda, visita la guía de referencia del archivo .dockerignore en
# https://docs-docker.esdocu.com/go/build-context-dockerignore/
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/.next
**/.cache
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/charts
**/docker-compose*
**/compose.y*ml
**/target
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
**/vendor
LICENSE
README.mdAhora deberías tener los siguientes tres archivos en tu directorio spring-petclinic.
Ejecuta la aplicación
Dentro del directorio spring-petclinic, ejecuta el siguiente comando en una terminal.
$ docker compose up --build
La primera vez que construyas y ejecutes la aplicación, Docker descargará las dependencias y construirá la aplicación. Puede tomar varios minutos dependiendo de tu conexión de red.
Abre un navegador y visualiza la aplicación en http://localhost:8080. Deberías ver una aplicación sencilla para una clínica de mascotas.
En la terminal, presiona ctrl+c para detener la aplicación.
Ejecuta la aplicación en segundo plano
Puedes ejecutar la aplicación desacoplada de la terminal agregando la opción -d. Dentro del directorio spring-petclinic, ejecuta el siguiente comando en una terminal.
$ docker compose up --build -d
Abre un navegador y visualiza la aplicación en http://localhost:8080. Deberías ver una aplicación sencilla para una clínica de mascotas.
En la terminal, ejecuta el siguiente comando para detener la aplicación.
$ docker compose down
Para obtener más información sobre los comandos de Compose, consulta la referencia de la CLI de Compose.
Resumen
En esta sección, aprendiste cómo puedes contenedorizar y ejecutar una aplicación Java utilizando Docker.
Información relacionada:
Siguientes pasos
En la siguiente sección, aprenderás cómo puedes desarrollar tu aplicación utilizando contenedores de Docker.