---
title: "Desarrollando con Quarkus en VS Code usando Dev Containers"
author: "Gisela Torres"
date: "2026-02-21"
categories: ["Contenedores"]
tags: ["Dev Containers", "Java", "Quarkus", "Visual Studio Code"]
url: "https://www.returngis.net/2026/02/desarrollando-con-quarkus-en-vs-code-usando-dev-containers/"
---

# Desarrollando con Quarkus en VS Code usando Dev Containers

¡Hola developer 👋🏻!  
A principios de semana te contaba [cómo estoy desarrollando actualmente mis aplicaciones con **Spring Boot** en **Visual Studio Code** gracias a **Dev Containers**](https://www.returngis.net/2026/02/mi-configuracion-de-dev-container-para-spring-boot/), y todo lo que podemos configurar como parte del entorno de desarrollo.

Pero… ¿y si tu framework preferido no es Spring Boot sino **Quarkus**?  
Entonces este artículo es para ti 😉

En esta ocasión quiero compartir la configuración de **Dev Container** que estoy utilizando para proyectos con Quarkus. 🚨 Aviso: me ha dado un poquito más de guerra que la de Spring Boot, pero después de varios ajustes, esta es la que estoy usando ahora mismo y me funciona perfectamente.

🎥 Antes de entrar en la configuración, si todavía no estás familiarizado con Dev Containers o quieres ver cómo los uso en mi día a día con Visual Studio Code, te dejo por aquí un vídeo donde lo explico paso a paso 👇🏻

https://youtu.be/DkKs29etRis

## 📁 `.devcontainer/devcontainer.json`

Esta es la configuración completa del Dev Container:

```
{
  "name": "Quarkus Dev Environment",
  "dockerComposeFile": "compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "customizations": {
    "vscode": {
      "extensions": [
        "redhat.java",
        "vscjava.vscode-java-pack",
        "vscjava.vscode-gradle",
        "redhat.vscode-quarkus",
        "redhat.vscode-microprofile",
        "redhat.vscode-yaml",
        "mtxr.sqltools",
        "mtxr.sqltools-driver-pg",
        "ms-azuretools.vscode-docker",
        "humao.rest-client"
      ],
      "settings": {
        "java.configuration.updateBuildConfiguration": "automatic",
        "java.server.launchMode": "Standard",
        "quarkus.tools.starter.api.base": "https://code.quarkus.io",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
          "source.organizeImports": "explicit"
        },
        "[java]": {
          "editor.defaultFormatter": "redhat.java"
        },
        "sqltools.connections": [
          {
            "name": "🐘 Sports DB (PostgreSQL)",
            "driver": "PostgreSQL",
            "server": "localhost",
            "port": 5432,
            "database": "sports_db",
            "username": "sports_user",
            "password": "sports_pass"
          }
        ]
      }
    }
  },
  "forwardPorts": [
    8080,
    5432
  ],
  "portsAttributes": {
    "8080": {
      "label": "🚀 Quarkus App",
      "onAutoForward": "notify"
    },
    "5432": {
      "label": "🐘 PostgreSQL",
      "onAutoForward": "silent"
    }
  },
  "remoteEnv": {
    "JAVA_HOME": "/usr/lib/jvm/msopenjdk-current"
  },
  "remoteUser": "vscode",
  "features": {
    "ghcr.io/devcontainers/features/github-cli:1": {
      "installDirectlyFromGitHubRelease": true,
      "version": "latest"
    },
    "ghcr.io/devcontainers-extra/features/quarkus-sdkman:2": {
      "version": "latest",
      "jdkVersion": "none",
      "jdkDistro": "ms"
    },
    "ghcr.io/devcontainers/features/java:1": {
      "installGradle": true,
      "version": "none",
      "jdkDistro": "ms",
      "gradleVersion": "8.10.2"
    }
  }
}
```

## 🐳 Docker Compose: aplicación + base de datos

En este caso estoy utilizando **Docker Compose** porque mi entorno está formado por **dos contenedores**:

- 🧩 **Aplicación Quarkus**
- 🐘 **Base de datos PostgreSQL**

```
services:
  app:
    image: mcr.microsoft.com/devcontainers/java:21-bookworm
    volumes:
      - ..:/workspace:cached
    command: sleep infinity
    network_mode: service:db
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: sports_user
      POSTGRES_PASSWORD: sports_pass
      POSTGRES_DB: sports_db
    ports:
      - "5432:5432"
      - "8080:8080"
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U sports_user -d sports_db"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  postgres-data:
```

De esta forma consigo que **todas las dependencias necesarias para el desarrollo formen parte del entorno**, sin tener que instalar nada en local. En este ejemplo solo tengo una base de datos, pero el patrón escala muy bien si mañana necesitas Redis, Kafka o cualquier otro servicio.

## 🧩 Extensiones y settings de VS Code

Como parte del Dev Container incluyo varias extensiones clave:

- Soporte completo para **Java y Gradle**
- Extensiones específicas de **Quarkus y MicroProfile**
- **SQLTools** para conectar directamente a PostgreSQL
- Docker, REST Client y YAML

Además, dejo preconfiguradas algunas **settings útiles**, como:

- Formateo automático al guardar
- Organización explícita de imports
- Conexión directa a la base de datos desde VS Code

Todo listo para empezar a trabajar nada más abrir el repositorio 🚀

## 🔌 Puertos y forwarding

También configuro explícitamente los puertos que necesito:

- `8080` → Aplicación Quarkus 🚀
- `5432` → PostgreSQL 🐘

Incluyendo etiquetas y comportamiento al auto-forward para que la experiencia sea más limpia y visual dentro de VS Code.

### 🧠 Por qué tuve que configurar `JAVA_HOME` en `remoteEnv`

En mi caso fue necesario definir explícitamente la variable de entorno `JAVA_HOME` dentro de la sección `remoteEnv` del Dev Container.

El motivo es que la *feature* `quarkus-sdkman` instala **SDKMAN** y configura automáticamente `JAVA_HOME` apuntando a la siguiente ruta:

```
/usr/local/sdkman/candidates/java/current
```

Sin embargo, en esta configuración **no estoy instalando el JDK vía SDKMAN**, ya que el JDK viene ya preinstalado en la imagen base de Microsoft (`mcr.microsoft.com/devcontainers/java:21-bookworm`).  
Esto hace que ese *symlink* no exista realmente en el contenedor.

👉 Como consecuencia, herramientas como **Gradle o Quarkus** intentan usar un `JAVA_HOME` que apunta a una ruta inexistente y la ejecución falla.

La solución es sencilla: forzar `JAVA_HOME` a la ubicación real del JDK que trae la imagen base:

```
/usr/lib/jvm/msopenjdk-current
```

Con este override me aseguro de que todas las herramientas Java utilizan el JDK correcto y el entorno funciona de forma estable y predecible.

## ⚠️ Muy importante: Quarkus debe escuchar en todas las interfaces

Puede que hayas llegado hasta aquí con tu propia configuración y que, al arrancar la aplicación, te hayas encontrado con un **timeout** al intentar acceder desde el navegador.

Esto es muy habitual y tiene una causa clara:  
👉 **Quarkus, por defecto, no escucha en todas las interfaces de red**.

La solución es sencilla. Solo tienes que añadir esta línea en tu `application.properties`:

```
# HTTP configuration - escuchar en todas las interfaces
quarkus.http.host=0.0.0.0
```

Con esto, tu aplicación será accesible correctamente desde tu máquina local, sin ensuciar tu entorno ni instalar nada en local 🎉

¡Nos vemos 👋🏻!
