The quick download
Quarkus Live Coding, also called Live Reload, works with Docker when the container runs in Quarkus development mode and is configured for remote development.
-
Generated Quarkus container configurations typically use production-style execution, so enable dev mode explicitly with
QUARKUS_LAUNCH_DEVMODE=true.
-
The workflow requires three elements: dev mode, a mutable JAR, and a reachable quarkusRemoteDev connection.
-
Keep Live Coding settings in application-dev.properties so a standard production build does not include them.
-
After development, use LogicMonitor to monitor the resulting service across containers, JVM resources, dependencies, and network performance before production traffic exposes an issue.
Quarkus Live Coding lets you edit source code and see changes in the running application after Quarkus automatically recompiles and reloads the affected code, without a manual rebuild or redeployment.
Locally, this happens automatically in dev mode. Inside a Docker container, it takes a few extra configuration steps because containers default to production mode, which disables Live Coding on purpose.
In this Quarkus Docker guide, we’ll cover how to create a Quarkus app, run it locally with Live Coding, and then get that same Live Coding workflow running inside a Docker container.
Disclaimer: Last verified against Quarkus 3.33 LTS (current as of mid-2026). Quarkus releases new minor versions every 4-6 weeks, so check quarkus.io/releases for the latest LTS before you pin a version in production.
Prerequisites
Install these before starting:
- JDK 17, 21, or 25, depending on the Quarkus version and project requirements
- Docker or Podman
- Gradle or Maven, preferably using the Maven or Gradle wrapper generated with the project.
Note:
Enable Live Coding in Docker
If you already have a Quarkus application and need the abbreviated workflow:
Step 1: Set QUARKUS_LAUNCH_DEVMODE=true as an environment variable on your Docker container.
Step 2: Add quarkus.package.jar.type=mutable-jar, quarkus.live-reload.password=, and quarkus.live-reload.url=https://localhost:8080 to application.properties or application-dev.properties.
Step 3: Build the JAR, build the Docker image, and run the container.
Step 4: Connect with ./gradlew quarkusRemoteDev (Gradle) or ./mvnw quarkus:remote-dev (Maven).
If you put the config in application-dev.properties, add -Dquarkus.profile=dev to both the build command and the remote-dev command. The rest of this guide walks through why each step is necessary and what to do when one of them doesn’t work.
Version Note: Examples were verified against Quarkus 3.33 LTS and Java 25. Confirm the current Quarkus LTS and generate Dockerfile templates before using these commands in a new project.
What Is Live Coding in Quarkus?
Live coding in Quarkus, also called Development Mode or dev mode, continuously monitors your source files and automatically rebuilds and reloads the application when you make changes by eliminating the need for manual restarts.
This only works in dev mode, not in a production build. It speeds up the loop of writing code and testing it, not to be part of how you deploy your app; you still use a normal, unchanging build everywhere else.
The workflow is: when your app runs in dev mode, it checks for source changes each time a request comes in. If something changed, Quarkus compiles just that part of the code and updates the running app before answering the request.
That first request after a change takes a bit longer because of the compile step; after that, things run at normal speed again until you make another edit.
This works the same way whether the app is running directly on your machine or inside a Docker container. The one difference with a container is that you have to tell it to run in dev mode and give your local Quarkus CLI a way to reach it.
How to Create My First Quarkus App
The most direct way to create a Quarkus project is the Quarkus CLI. Installation and Java or build-tool requirements depend on the selected setup, so verify them against the current Quarkus documentation.
Alternatively, code.quarkus.io generates the same project structure through a browser-based form.
With the CLI installed, create a new Gradle-based project:
quarkus create app --gradle org.acme:docker-live-codingFor Maven, drop the --gradle flag; Maven is the default build tool. Run quarkus create app --help to see the project-creation options, or quarkus -h to see the CLI’s other general help commands.
This creates a docker-live-coding directory with a working REST endpoint, a unit test for it, and a set of Dockerfiles already wired up for you.
What’s Inside the Generated Project?
The endpoint is present at src/main/java/org/acme/GreetingResource.java:
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from Quarkus REST";
}
}A matching test is at src/test/java/org/acme/GreetingResourceTest.java:
@QuarkusTest
public class GreetingResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("Hello from Quarkus REST"));
}
}The CLI also generates Dockerfiles in src/main/docker/:
| Dockerfile | Purpose |
|---|---|
| Dockerfile.jvm | This Dockerfile is used to build a container that runs the Quarkus application in JVM mode |
| Dockerfile.legacy-jar | The pre-Quarkus-1.12 JAR layout. Only relevant if you’re maintaining an older project. |
| Dockerfile.native | This Dockerfile is used to build a container that runs the Quarkus application in native (no JVM) mode. It copies in a native executable, already compiled separately with GraalVM. |
| Dockerfile.native-micro | The same native build on a smaller, more minimal base image. |
How Do I Run My Quarkus App Locally in Dev Mode?
You can run it from the project directory:
CLI
quarkus dev
Gradle
./gradlew quarkusDev
Maven
./mvnw quarkus:dev
Once it starts, you’ll see a log line confirming dev mode and Live Coding are active, and your app is reachable at http://localhost:8080. Open a second terminal and send a request to http://localhost:8080/hello. You should receive: Hello from Quarkus REST.
How Does Live Reload Work in Quarkus Dev Mode?
With the app still running, edit GreetingResource.java:
public String hello() {
return "Hello from Quarkus REST. How are you?";
}Save the file, then run the same curl command again. The next request should reflect the new text after Quarkus detects the change, recompiles the affected source, and redeploys the application in dev mode.
Quarkus detected the change on the next incoming request and recompiled only what changed before serving it. Simple edits like this one, which only change a method body, are usually applied through Quarkus’s state-preserving reload, so the app doesn’t lose its in-memory state.
Structural changes like adding a field or changing a method signature trigger a full application restart instead, which does reset state.
How Do I Use a Dockerfile for Quarkus Live Coding?
First, build the JAR.
Using the Quarkus CLI:
quarkus build
Using Gradle:
./gradlew build
Using Maven:
./mvnw package
If you leave the hello() change in place from the previous step, either revert it or update the test, the build fails if the test doesn’t match the endpoint.
Build the image with Dockerfile.jvm:
docker build -f src/main/docker/Dockerfile.jvm -t quarkus/docker-live-coding .
Run it:
docker run -i --rm -p 8080:8080 quarkus/docker-live-coding
Curl the endpoint again, and you’ll get the original greeting back. The container doesn’t have your local uncommitted changes baked in unless you rebuilt the image with them. Editing the source file while this container is running does not change the application.
The startup logs explain why: Profile prod activated. A container built from Dockerfile.jvm runs in production mode, and production mode has no Live Coding to activate.
Why Doesn’t Live Coding Work in Docker by Default?
Live Coding is a dev-mode-only feature, and the default Dockerfiles Quarkus generates are built for production mode.
Getting Live Coding working in a container means telling that container to run in dev mode instead, then giving your local machine a way to connect to it and push source changes.
Docker isolates the container filesystem from the host, so the container cannot watch local source files in the same way as Quarkus dev.
A typical remote-development workflow requires:
- Quarkus development mode, enabled with
QUARKUS_LAUNCH_DEVMODE=true - a mutable JAR and write access to the deployment resources
- a reachable remote-development endpoint and the required authentication password.
The next three sections cover each one.
How to Configure Docker for quarkusRemoteDev
Follow these steps:
Step 1: Switch the Container to dev Mode
Add this environment variable to your Dockerfile:
ENV QUARKUS_LAUNCH_DEVMODE=true
Rather than editing Dockerfile.jvm directly, copy it to a new Dockerfile.dev so you keep a clean production reference. Since this Dockerfile copies in an already-built JAR rather than compiling inside the container, use the runtime variant of the base image (openjdk-25-runtime), not the full builder image:
FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24-3.1786536503
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
COPY --chown=185 build/quarkus-app/lib/ /deployments/lib/
COPY --chown=185 build/quarkus-app/*.jar /deployments/
COPY --chown=185 build/quarkus-app/app/ /deployments/app/
COPY --chown=185 build/quarkus-app/quarkus/ /deployments/quarkus/
RUN chmod o+rw -R /deployments
EXPOSE 8080
USER 185
ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
ENV QUARKUS_LAUNCH_DEVMODE=trueregistry.access.redhat.com/ubi9/openjdk-25-runtime is Red Hat’s official UBI9 OpenJDK 25 runtime image. See the Red Hat Ecosystem Catalog listing for the current tag before you pin one; it’s a recent addition (GA in December 2025), so confirm the tag is still current rather than copying it verbatim from this guide.
If the Quarkus CLI generates a slightly different Dockerfile.jvm for your version, that’s expected. Quarkus updates these templates over time. As long as the QUARKUS_LAUNCH_DEVMODE=true line is present, the rest of this walkthrough applies.
The RUN chmod o+rw -R /deployments line is required and easy to miss: without it, the container doesn’t have write permission to update its own deployment files, so the remote-dev connection you’ll set up next can’t actually push your code changes into the running app.
Step 2: Make the Build Mutable and Reachable
Open application.properties (in src/main/resources) and add:
quarkus.package.type=mutable-jar
quarkus.live-reload.password=changeit
quarkus.live-reload.url=https://localhost:8080mutable-jar tells Quarkus to package the build so the running application can be updated in place; a standard fast-jar build can’t be.
Replace changeit with a real password; even for local-only use, it’s worth doing correctly, because Quarkus also supports remote Live Coding against non-local machines, and a default password there is a real credential exposed to the network.
quarkus.live-reload.url is technically optional. You can pass it as a command-line flag instead, but setting it here means you don’t have to remember it later.
Step 3: Build and Run the dev-mode Container
Run the following commands:
quarkus build
docker build -f src/main/docker/Dockerfile.dev -t quarkus/docker-live-coding .
docker run -i --rm -p 8080:8080 quarkus/docker-live-codingMaven equivalent for the first command: ./mvnw package.
Step 4: Connect Your Local Machine to the Container
In a new terminal, from your project directory, run:
./gradlew quarkusRemoteDev
For Maven:
./mvnw quarkus:remote-dev.
If you didn’t set `quarkus.live-reload.url` in application.properties, pass it explicitly:
./gradlew quarkusRemoteDev -Dquarkus.live-reload.url=https://localhost:8080
A successful connection logs Connected to remote server. From here, edit your source file and curl the endpoint the same way you did locally. The container picks up the change through the remote-dev connection.
How to Scope Live Coding to a Dev Profile Only
The config from the previous section applies to every build, including one you might accidentally ship to production. A mutable JAR with live-reload enabled has no place outside a development environment, so the fix is to move those three properties into a profile-specific file instead of the shared application.properties.
Create application-dev.properties next to the existing application.properties, and move the three Live Coding properties into it.
Quarkus requires application.properties to still exist in that same location, even if empty, for the profile-specific file to be chosen at all, so don’t delete it once you’ve moved the properties out:
quarkus.package.jar.type=mutable-jar
quarkus.live-reload.password=changeit
quarkus.live-reload.url=https://localhost:8080Now these settings apply only when you explicitly build with the dev profile:
quarkus build -Dquarkus.profile=dev
./gradlew quarkusRemoteDev -Dquarkus.profile=devFor Maven:
./mvnw package -Dquarkus.profile=dev and ./mvnw quarkus:remote-dev -Dquarkus.profile=dev.
Build without the profile flag, and Quarkus ignores the dev-only properties entirely, so a standard production build stays a standard production build.
Is It Safe to Use These Live Coding Configs in Production?
No, don’t run mutable-jar packaging or an active quarkus.live-reload connection in production. Both let a remote client push code changes into a live process, which is exactly what you don’t want outside a development environment.
Scoping these settings to application-dev.properties, as covered in the previous section, is what prevents that from happening by accident, since a normal Quarkus build with no profile flag never picks them up.
Treat any environment where Live Coding is accessible, including a shared dev or staging cluster, with the same access controls you’d use for a production secret.
What Are My Options for Building a Quarkus Container Image?
You don’t have to use docker build and docker run manually. Quarkus has extensions that build the image for you, usually without a hand-written Dockerfile. Which one to use depends on your setup.
Use one Quarkus container-image extension per build. If multiple builder extensions are present, select one explicitly with quarkus.container-image.builder or remove the others.
Choose Docker, Podman, Jib, Buildpacks, or OpenShift according to the build environment; do not enable multiple providers for the same build unless the selection is explicitly controlled.
Docker
Use this if you’re already comfortable with Dockerfiles. It uses the Docker binary and the Dockerfiles Quarkus already generated under src/main/docker.
Here’s how to use it:
CLI:
quarkus extension add quarkus-container-image-docker
Maven:
./mvnw quarkus:add-extension -Dextensions='quarkus-container-image-docker'
Gradle:
./gradlew addExtension --extensions='quarkus-container-image-docker'
This extension can also build multi-platform images using docker buildx. But docker buildx build only loads the result into a single platform’s Docker image.
If you set quarkus.docker.buildx.platform to more than one platform (for example, linux/amd64,linux/arm64), the images won’t show up locally. You need to push them with quarkus.container-image.push=true as part of the same build instead, since Docker buildx cannot load a multi-platform result into the local Docker image store; push it to a registry as part of the build.
Podman
Use this if you need something Podman does that Docker doesn’t, such as native multi-platform builds. Otherwise, the Docker extension above already works with Podman, since Podman exposes a Docker-compatible API.
Here’s how to add the following extensions:
CLI:
quarkus extension add quarkus-container-image-podman
Maven:
./mvnw quarkus:add-extension -Dextensions='quarkus-container-image-podman'
Gradle:
./gradlew addExtension --extensions='quarkus-container-image-podman'
Jib
Use this in CI environments without a Docker daemon. Jib builds and pushes the image directly, with no Docker build step.
Here’s how to add the following extensions:
CLI:
quarkus extension add quarkus-container-image-jib
Maven:
./mvnw quarkus:add-extension -Dextensions='quarkus-container-image-jib'
Gradle:
./gradlew addExtension --extensions='quarkus-container-image-jib'
Buildpacks
Use this if you want to skip writing or maintaining a Dockerfile. Buildpacks builds the image from your build output using a standard process instead.
Here’s how to add the following extensions:
CLI:
quarkus extension add quarkus-container-image-buildpack
Maven:
./mvnw quarkus:add-extension -Dextensions='quarkus-container-image-buildpack'
Gradle:
./gradlew addExtension --extensions='quarkus-container-image-buildpack'
Buildpacks still needs a Docker daemon behind the scenes for the actual build. Unlike the other extensions, it doesn’t ship with a default builder image, so you have to set quarkus.buildpack.jvm-builder-image (and quarkus.buildpack.native-builder-image for native builds) yourself.
OpenShift Binary Build
Use this to build directly inside an OpenShift cluster. You upload your build artifacts, and OpenShift merges them into a builder image as part of the build.
Here’s how to add the following extensions:
CLI:
quarkus extension add quarkus-container-image-openshift
Maven:
./mvnw quarkus:add-extension -Dextensions='quarkus-container-image-openshift'
Gradle:
./gradlew addExtension --extensions='quarkus-container-image-openshift'
Building and Pushing, Once an Extension Is Added
To build a container image, set quarkus.container-image.build=true using whichever of these matches your setup:
CLI:
quarkus build
Maven:
./mvnw install -Dquarkus.container-image.build=true
Gradle:
./gradlew build -Dquarkus.container-image.build=true
If you already have a native image built and just want to rebuild the container around it, add -Dquarkus.native.reuse-existing=true and Quarkus skips re-running the native build.
To push the image, set quarkus.container-image.push=true. If you don’t set a registry with quarkus.container-image.registry, Quarkus pushes to docker.io by default.
For Buildpacks, avoid setting quarkus.container-image.build=true permanently in application properties because it can trigger nested builds (builds inside builds). Pass the property on the build command instead. Pass it as a -D flag on the build command instead: -Dquarkus.container-image.build=true directly on the command line.
How to Debug a Quarkus Application Inside a Container
Container debugging is separate from Live Coding. For a JVM build, start the application with the Java debug agent enabled, expose the debug port from the container, and map that port to the host so an IDE or debugger can attach.
Keep the port restricted to the development environment and avoid exposing it through a shared or public interface.
Native executables require a different workflow. Build the executable with debug symbols and use gdb or an equivalent native debugger; a production-stripped binary does not contain enough information for source-level debugging.
JVM-only tests may also need to be excluded from native or HTTP-only integration runs. Use Quarkus test annotations such as @DisabledOnIntegrationTest where a test depends on JVM-specific behavior.
How to Run a Live Coding Container with Docker Compose
If you’re already running other services locally, like a database or a message broker, Compose is a cleaner way to start the dev-mode container alongside them than a long docker run command. Here’s a minimal docker-compose.yml for the setup above:
services:
docker-live-coding:
build:
context: .
dockerfile: src/main/docker/Dockerfile.dev
ports:
- "8080:8080"
environment:
QUARKUS_LAUNCH_DEVMODE: "true"Build the JAR first with quarkus build (or the Gradle or Maven equivalent), the same as before. Then start the stack with docker compose up –build, and connect with ./gradlew quarkusRemoteDev (or the Maven equivalent) just like you would without Compose. The remote-dev connection still targets localhost:8080, whether Docker or Compose started the container.
How to Build and Run a Native Quarkus Executable in Docker
A native executable is your Quarkus app compiled ahead of time with GraalVM into a standalone binary that skips the JVM entirely, giving you a much smaller image and near-instant startup.
The downside is a longer build, and you lose Live Coding along the way, so think of this as a separate workflow you reach for once you’re getting closer to a production image, not something you use day-to-day.
You don’t need GraalVM installed on your machine if you build inside a container instead:
Run quarkus build --native --no-tests -Dquarkus.native.container-build=true (or the Maven or Gradle equivalent), then build and run the generated Dockerfile.native the same way you already built and ran Dockerfile.jvm earlier in this guide.
Two things worth knowing before you try it:
- The executable you get is a 64-bit Linux binary, so if you’re on macOS or Windows and you skip the container build. It won’t run in a Linux container.
- Since Quarkus 3.19, the container build uses a UBI9-based builder image, so don’t pair the result with a UBI8 base image in your Dockerfile. It won’t run.
Which Base Image Should I Use?
The right base image depends on what you’re deploying:
| Base image | Fits | Tradeoff |
|---|---|---|
| Standard UBI (ubi9/openjdk-25) | JVM-mode apps, general use | Bigger image, but it has everything a JVM app needs already installed, so you won’t hit missing-dependency errors |
| UBI Micro | Native executables | Small image that still has what native builds need; the default for Dockerfile.native-micro |
| Distroless | Native executables, advanced use | No shell, smaller attack surface. Quarkus calls this experimental and says to test it thoroughly before using it in production |
| Scratch | Fully statically linked native executables, typically built with musl | Smallest image possible. Quarkus says not to use it in production without thorough testing, since anything that needs a system library at runtime, like a DNS lookup, can fail unless the binary is fully static |
Troubleshooting Live Coding in Docker
If Live Coding isn’t working, check these first:
- Dev mode won’t activate: Check the container startup logs for Profile dev activated. Live Coding activated. If the logs show Profile prod activated, the
QUARKUS_LAUNCH_DEVMODE=trueenvironment variable isn’t reaching the container. Confirm it’s in the Dockerfile you actually built with, not left over in an unused one. - The main app reloads, but changes to a library module in the same project: If your project is multi-module (a separate library alongside your main app),
quarkusRemoteDevcan silently skip reloading the library even though local quarkus dev uses the same change fine. Quarkus logs a warning like Live reload was disabled for the following project artifacts: … The artifacts above appear to be either dependencies of non-reloadable application dependencies or Quarkus extensions. - Code changes aren’t reflected after
quarkusRemoteDevconnects: Confirmquarkus.package.type=mutable-jarwas set at build time. If you built the JAR before adding that property, rebuild it. Also confirm you’re editing the file in the project you actually connected from; quarkusRemoteDev syncs from the local project directory, not from inside the container.
Validate the Service Beyond Development
Once the Docker development workflow is working, validate the service as it will run beyond development. Keep the dev profile, mutable JAR, and remote Live Coding connection out of production builds, then test the resulting image with production-like traffic and dependencies.
Live Coding confirms that source changes can be applied quickly during development. It does not show whether the deployed container will remain healthy, whether dependencies are creating latency, or whether resource pressure will affect users.
LogicMonitor stands out by connecting those production signals in one operational view: container health and restarts, JVM memory and garbage collection, application response time and errors, host or cluster pressure, dependency latency, network-path performance, and deployment changes.
That cross-layer context helps teams move from an application symptom to the infrastructure or dependency that caused it, across cloud, container, and hybrid environments.
LogicMonitor Supports Production Readiness
Use LogicMonitor to carry visibility from deployment through production operation, with the context needed to identify performance issues before they become user-facing incidents.
FAQs
Does This Still Work if I’m on an Older Quarkus Version?
The Live Coding mechanism and the QUARKUS_LAUNCH_DEVMODE / mutable-jar / live-reload configuration have been stable since early Quarkus 2.x. The container-image extensions, Docker Compose approach, and native-build flags in this guide assume a current 3.x release; check the Quarkus migration guides if you’re upgrading from 2.x.
Can I Use Live Coding With Kubernetes or OpenShift, Not Just Local Docker?
Yes, Quarkus supports remote development against containers running in Kubernetes, Minikube, and OpenShift using the same underlying mechanism: dev mode, a mutable build, and a quarkusRemoteDev connection to a reachable URL.
Why Does Live Coding Not Work in Docker by Default?
Generated Dockerfiles are intended for production-style execution and start the application in the prod profile. Enable dev mode explicitly with QUARKUS_LAUNCH_DEVMODE=true, use a mutable JAR, and establish the quarkusRemoteDev connection.
Are Mutable JAR and Live Coding Settings Safe in Production?
No. Keep mutable-jar packaging, Live Coding passwords, and remote reload connections in a development-only profile. A standard production build should not include settings that allow a client to push code into a running process.
What Should I Check When quarkusRemoteDev Cannot Connect?
Confirm that the container is running in dev mode, the remote URL is reachable from the host, the Live Coding password matches, port 8080 is mapped correctly, and the JAR was rebuilt after mutable-jar was enabled. Check the container logs for the active profile and connection status.
Does the Native Workflow Support Live Coding?
No, native builds are a separate packaging path for deployment-oriented testing and production preparation. Use JVM dev mode for Live Coding, then validate the native executable separately.
Do I Need a Current Quarkus Version for These Commands?
The core Live Coding workflow is available across multiple Quarkus generations, but the container-image extensions, Java baseline, Dockerfile templates, and native-build options change. Verify the commands against the Quarkus release and JDK version you plan to use.



