In my previous article, I shared with you the steps I took, to remotely debug a Java application that is running in a container on a Kubernetes cluster in my already existing Linux demo environment.
[Quarkus – Kubernetes extension (reinvestigated, part 6), Remote debugging a Java application that is running in a container on a K3s Kubernetes cluster]
Some years ago, I also wrote articles about the Quarkus Kubernetes Extension.
As a mentioned in my previous article, I wanted to have a look at some others aspects of the Quarkus Kubernetes Extension, that I came across.
Part of the “Developer Joy” is the so called “Remote Development”.
Run dev mode remotely with changes to local files immediately available in a containerize environment.
Read the Remote Development Mode guide
[https://quarkus.io/developer-joy/]
Warning:
Do not use this in production. This should only be used in a development environment. You should not run production application in dev mode.
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
In my previous article the focus was on remote debugging.
In this article, you can read more about “Live Coding” and the remote development mode, so that changes made to the local files of a Java application that is running in a container on a Kubernetes cluster, become immediately visible.
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
The base for all of this was my already existing Linux demo environment, including Quarkus and K3s (a lightweight certified Kubernetes distribution) and setup via Vagrant, as described in a previous article.
[Quarkus – Kubernetes extension (reinvestigated, part 5), implementing a Service of service type LoadBalancer with K3s]
I started with reading the “Remote Development Mode guide”.
Live Coding
Improve and expedite the inner loop development process with live coding where code changes are automatically reflected in your running application. code -> refresh browser -> repeat
Read the Dev Mode guide
[https://quarkus.io/developer-joy/]
Development mode
Dev mode enables hot deployment with background compilation, which means that when you modify your Java files or your resource files and refresh your browser these changes will automatically take effect. This works too for resource files like the configuration property file. The act of refreshing the browser triggers a scan of the workspace, and if any changes are detected the Java files are compiled, and the application is redeployed, then your request is serviced by the redeployed application. If there are any issues with compilation or deployment an error page will let you know.
[https://quarkus.io/guides/maven-tooling#dev-mode]
Remote development mode
It is possible to use development mode remotely, so that you can run Quarkus in a container environment (such as OpenShift) and have changes made to your local files become immediately visible.
This allows you to develop in the same environment you will actually run your app in, and with access to the same services.
| Do not use this in production. This should only be used in a development environment. You should not run production application in dev mode. |
To do this you must build a mutable application, using the mutable-jar format. Set the following properties in application.properties:
quarkus.package.jar.type=mutable-jar (1) quarkus.live-reload.password=changeit (2) quarkus.live-reload.url=http://my.cluster.host.com:8080 (3)
- This tells Quarkus to use the mutable-jar format. Mutable applications also include the deployment time parts of Quarkus, so they take up a bit more disk space. If run normally they start just as fast and use the same memory as an immutable application, however they can also be started in dev mode.
- The password that is used to secure communication between the remote side and the local side.
- The URL that your app is going to be running in dev mode at. This is only needed on the local side, so you may want to leave it out of the properties file and specify it as a system property on the command line.
The mutable-jar is then built in the same way that a regular Quarkus jar is built, i.e. by issuing:
Before you start Quarkus on the remote host set the environment variable QUARKUS_LAUNCH_DEVMODE=true. If you are on bare metal you can set it via the export QUARKUS_LAUNCH_DEVMODE=true command and then run the application with the proper java -jar … command to run the application.
If you plan on running the application via Docker, then you’ll need to add -e QUARKUS_LAUNCH_DEVMODE=true to the docker run command. When the application starts you should now see the following line in the logs: Profile dev activated. Live Coding activated. You will also need to give the application the rights to update the deployment resources by adding RUN chmod o+rw -R /deployments after the COPY commands into your Dockerfile. For security reasons, this option should not be added to the production Dockerfile.
| The remote side does not need to include Maven or any other development tools. The normal fast-jar Dockerfile that is generated with a new Quarkus application is all you need. If you are using bare metal launch the Quarkus runner jar, do not attempt to run normal dev mode. |
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
So, in line with the “Remote Development Mode guide”, I proceeded with making some changes.
Setting up the application for using the remote development mode
Below, you can see an overview of my Linux demo environment, as described in my previous article:
[Quarkus – Kubernetes extension (reinvestigated, part 6), Remote debugging a Java application that is running in a container on a K3s Kubernetes cluster]
So, next I wanted to try out the remote development mode, by running the “kubernetes-quickstart” application on my Linux demo environment and start making changes to my local files on my Windows laptop where I had the source code available in the IntelliJ IDEA.
For the Linux demo environment to start, from the Oracle VM VirtualBox Manager on my Windows laptop, I started the appliance (in “Headless Start” mode).
Once the VM was running, for executing later manual steps, I used vagrant ssh to connect into the running VM.
Before I proceeded with the steps mentioned in the “Remote Development Mode guide”, I wanted to make some changes to the “kubernetes-quickstart” application, to simplify some things. I wanted to skip the remote debugging and only wanted 1 pod with 1 container with the running application.
Next, on my Windows laptop, in my shared folder, I navigated to kubernetes-quickstart\src\main\resources and changed the content of file application.properties to:
[in bold, I highlighted the changes]
quarkus.container-image.registry=localhost:8443 quarkus.container-image.username=mylocregusername quarkus.container-image.password=mylocregpassword quarkus.container-image.group=quarkus quarkus.kubernetes.namespace=nl-amis-development quarkus.kubernetes.ports."ports".container-port=8080 quarkus.kubernetes.ports."ports".host-port=8180 quarkus.kubernetes.ports."ports".node-port=30010 quarkus.kubernetes.replicas=1 quarkus.kubernetes.service-type=node-portquarkus.kubernetes.remote-debug.enabled=truequarkus.kubernetes.remote-debug.address-port=5005
Following the steps mentioned in the “Remote Development Mode guide”, next I changed the content of file application.properties to:
[in bold, I highlighted the changes]
quarkus.container-image.registry=localhost:8443 quarkus.container-image.username=mylocregusername quarkus.container-image.password=mylocregpassword quarkus.container-image.group=quarkus quarkus.kubernetes.namespace=nl-amis-development quarkus.kubernetes.ports."ports".container-port=8080 quarkus.kubernetes.ports."ports".host-port=8180 quarkus.kubernetes.ports."ports".node-port=30010 quarkus.kubernetes.replicas=1 quarkus.package.jar.type=mutable-jar (1) quarkus.live-reload.password=mylivereloadpassword (2)
Step 1 tells Quarkus to use the mutable-jar format. Mutable applications also include the deployment time parts of Quarkus, so they take up a bit more disk space. If run normally they start just as fast and use the same memory as an immutable application, however they can also be started in dev mode.
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
Step 2 is the password that is used to secure communication between the remote side and the local side.
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
Remark about step 3:
As described in step 3, I opted to leave the URL out of the properties file, because it is only needed on the local side, and instead I will specify it as a system property on the command line.
Remark about quarkus.package.jar.type:
| Packaging the application property | Type | Default |
|---|---|---|
| quarkus.package.jar.type The JAR output type to use. Environment variable: QUARKUS_PACKAGE_JAR_TYPE |
fast-jar, uber-jar, mutable-jar, legacy-jar |
fast-jar |
[https://quarkus.io/guides/all-config]
Remark about quarkus.live-reload.password:
| Live reload property | Type | Default |
|---|---|---|
| quarkus.live-reload.password Password used to use to connect to the remote dev-mode application Environment variable: QUARKUS_LIVE_RELOAD_PASSWORD |
string |
[https://quarkus.io/guides/all-config]
Setting the environment variable QUARKUS_LAUNCH_DEVMODE=true
As the “Remote Development Mode guide” mentioned, before you start Quarkus on the remote host set the environment variable QUARKUS_LAUNCH_DEVMODE=true.
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
So, in order to add the environment variable, I changed the content of file application.properties to:
[in bold, I highlighted the changes]
quarkus.container-image.registry=localhost:8443 quarkus.container-image.username=mylocregusername quarkus.container-image.password=mylocregpassword quarkus.container-image.group=quarkus quarkus.kubernetes.namespace=nl-amis-development quarkus.kubernetes.ports."ports".container-port=8080 quarkus.kubernetes.ports."ports".host-port=8180 quarkus.kubernetes.ports."ports".node-port=30010 quarkus.kubernetes.replicas=1 quarkus.package.jar.type=mutable-jar quarkus.live-reload.password=mylivereloadpassword quarkus.kubernetes.env.vars.QUARKUS_LAUNCH_DEVMODE=true
Remark about adding a key/value pair as an environment variable:
To add a key/value pair as an environment variable in the generated resources:
quarkus.kubernetes.env.vars.my-env-var=foobar
The command above will add MY_ENV_VAR=foobar as an environment variable. Please note that the key my-env-var will be converted to uppercase and dashes will be replaced by underscores resulting in MY_ENV_VAR.
[https://quarkus.io/guides/deploying-to-kubernetes#environment-variables-from-keyvalue-pairs]
Generation of Kubernetes manifests
In order to recreate the Kubernetes manifests, I used the following commands on the Linux Command Prompt:
cd /mnt/mysharedfolder/kubernetes-quickstart mvn clean install -DskipTests
Remark about skipping tests:
To skip running the tests for a particular project, via the command line use -DskipTests.
[https://maven.apache.org/surefire/maven-surefire-plugin/examples/skipping-tests.html]
With the following output:
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called WARNING: sun.misc.Unsafe::staticFieldBase has been called by com.google.inject.internal.aop.HiddenClassDefiner (file:/opt/apache-maven-3.9.11/lib/guice-5.1.0-classes.jar) WARNING: Please consider reporting this to the maintainers of class com.google.inject.internal.aop.HiddenClassDefiner WARNING: sun.misc.Unsafe::staticFieldBase will be removed in a future release [INFO] Scanning for projects... [INFO] [INFO] -------------------< org.acme:kubernetes-quickstart >------------------- [INFO] Building kubernetes-quickstart 1.0.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- clean:3.2.0:clean (default-clean) @ kubernetes-quickstart --- [INFO] Deleting /mnt/mysharedfolder/kubernetes-quickstart/target [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ kubernetes-quickstart --- [INFO] Copying 1 resource from src/main/resources to target/classes [INFO] [INFO] --- quarkus:3.25.2:generate-code (default) @ kubernetes-quickstart --- [INFO] [INFO] --- compiler:3.14.0:compile (default-compile) @ kubernetes-quickstart --- [INFO] Recompiling the module because of changed source code. [INFO] Compiling 1 source file with javac [debug parameters release 21] to target/classes [INFO] [INFO] --- quarkus:3.25.2:generate-code-tests (default) @ kubernetes-quickstart --- [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ kubernetes-quickstart --- [INFO] skip non existing resourceDirectory /mnt/mysharedfolder/kubernetes-quickstart/src/test/resources [INFO] [INFO] --- compiler:3.14.0:testCompile (default-testCompile) @ kubernetes-quickstart --- [INFO] Recompiling the module because of changed dependency. [INFO] Compiling 2 source files with javac [debug parameters release 21] to target/test-classes [INFO] [INFO] --- surefire:3.5.3:test (default-test) @ kubernetes-quickstart --- [INFO] Tests are skipped. [INFO] [INFO] --- jar:3.4.1:jar (default-jar) @ kubernetes-quickstart --- [INFO] Building jar: /mnt/mysharedfolder/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar [INFO] [INFO] --- quarkus:3.25.2:build (default) @ kubernetes-quickstart --- [INFO] [io.quarkus.kubernetes.deployment.PropertyUtil] Kubernetes manifests are generated with 'The container port http' having default value '8080'. The app and manifests will get out of sync if the property 'quarkus.http.port' is changed at runtime. [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 19.864 s [INFO] Finished at: 2025-11-06T12:57:54Z [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal io.quarkus.platform:quarkus-maven-plugin:3.25.2:build (default) on project kubernetes-quickstart: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors [ERROR] [error]: Build step io.quarkus.kubernetes.deployment.KubernetesProcessor#build threw an exception: java.lang.RuntimeException: Can't edit matching ports. No match found. [ERROR] at io.fabric8.kubernetes.api.model.ServiceSpecFluent.editMatchingPort(ServiceSpecFluent.java:731) [ERROR] at io.quarkus.kubernetes.deployment.AddNodePortDecorator.andThenVisit(AddNodePortDecorator.java:35) [ERROR] at io.quarkus.kubernetes.deployment.AddNodePortDecorator.andThenVisit(AddNodePortDecorator.java:15) [ERROR] at io.dekorate.kubernetes.decorator.NamedResourceDecorator.andThenVisit(NamedResourceDecorator.java:90) [ERROR] at io.dekorate.kubernetes.decorator.NamedResourceDecorator$ResourceVisitor.visit(NamedResourceDecorator.java:105) [ERROR] at io.fabric8.kubernetes.api.builder.Visitor.visit(Visitor.java:30) [ERROR] at io.fabric8.kubernetes.api.builder.VisitorWiretap.visit(VisitorWiretap.java:49) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:53) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.lambda$accept$1(Visitable.java:67) [ERROR] at java.base/java.util.Optional.ifPresent(Optional.java:178) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:59) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:39) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:35) [ERROR] at io.dekorate.kubernetes.decorator.NamedResourceDecorator.visit(NamedResourceDecorator.java:63) [ERROR] at io.dekorate.kubernetes.decorator.NamedResourceDecorator.visit(NamedResourceDecorator.java:29) [ERROR] at io.fabric8.kubernetes.api.builder.Visitor.visit(Visitor.java:30) [ERROR] at io.fabric8.kubernetes.api.builder.VisitorWiretap.visit(VisitorWiretap.java:49) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:53) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.lambda$accept$1(Visitable.java:67) [ERROR] at java.base/java.util.Optional.ifPresent(Optional.java:178) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:59) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:39) [ERROR] at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:35) [ERROR] at io.dekorate.ResourceRegistry.lambda$generate$2(ResourceRegistry.java:181) [ERROR] at java.base/java.util.HashMap.forEach(HashMap.java:1430) [ERROR] at io.dekorate.ResourceRegistry.generate(ResourceRegistry.java:173) [ERROR] at io.dekorate.Session.generate(Session.java:293) [ERROR] at io.dekorate.Session.close(Session.java:256) [ERROR] at io.quarkus.kubernetes.deployment.KubernetesProcessor.lambda$build$5(KubernetesProcessor.java:198) [ERROR] at java.base/java.util.Optional.ifPresent(Optional.java:178) [ERROR] at io.quarkus.kubernetes.deployment.KubernetesProcessor.build(KubernetesProcessor.java:141) [ERROR] at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:735) [ERROR] at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:889) [ERROR] at io.quarkus.builder.BuildContext.run(BuildContext.java:255) [ERROR] at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18) [ERROR] at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2651) [ERROR] at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2630) [ERROR] at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1622) [ERROR] at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1589) [ERROR] at java.base/java.lang.Thread.run(Thread.java:1447) [ERROR] at org.jboss.threads.JBossThread.run(JBossThread.java:501) [ERROR] -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
So, I got an error:
Can't edit matching ports. No match found.
In this case there are no Kubernetes manifest files created in the target/kubernetes/ directory.
I stumbled across this error before, as I described in a previous article.
Again, the workaround for me, was to temporary change the port from 8080 to for example 8090 in the line quarkus.kubernetes.ports.”ports”.container-port=8080 in the file application.properties and then execute the mvn clean install command, followed by an undo of that port change and then execute the mvn clean install command again, until the build succeeded and the Kubernetes manifest files were created again.
[Quarkus – Kubernetes extension (reinvestigated, part 4), implementing a Service of service type NodePort]
In order to recreate the Kubernetes manifests again, I used the following commands on the Linux Command Prompt:
cd /mnt/mysharedfolder/kubernetes-quickstart mvn clean install -DskipTests
With the following output:
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called WARNING: sun.misc.Unsafe::staticFieldBase has been called by com.google.inject.internal.aop.HiddenClassDefiner (file:/opt/apache-maven-3.9.11/lib/guice-5.1.0-classes.jar) WARNING: Please consider reporting this to the maintainers of class com.google.inject.internal.aop.HiddenClassDefiner WARNING: sun.misc.Unsafe::staticFieldBase will be removed in a future release [INFO] Scanning for projects... [INFO] [INFO] -------------------< org.acme:kubernetes-quickstart >------------------- [INFO] Building kubernetes-quickstart 1.0.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- clean:3.2.0:clean (default-clean) @ kubernetes-quickstart --- [INFO] Deleting /mnt/mysharedfolder/kubernetes-quickstart/target [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ kubernetes-quickstart --- [INFO] Copying 1 resource from src/main/resources to target/classes [INFO] [INFO] --- quarkus:3.25.2:generate-code (default) @ kubernetes-quickstart --- [INFO] [INFO] --- compiler:3.14.0:compile (default-compile) @ kubernetes-quickstart --- [INFO] Recompiling the module because of changed source code. [INFO] Compiling 1 source file with javac [debug parameters release 21] to target/classes [INFO] [INFO] --- quarkus:3.25.2:generate-code-tests (default) @ kubernetes-quickstart --- [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ kubernetes-quickstart --- [INFO] skip non existing resourceDirectory /mnt/mysharedfolder/kubernetes-quickstart/src/test/resources [INFO] [INFO] --- compiler:3.14.0:testCompile (default-testCompile) @ kubernetes-quickstart --- [INFO] Recompiling the module because of changed dependency. [INFO] Compiling 2 source files with javac [debug parameters release 21] to target/test-classes [INFO] [INFO] --- surefire:3.5.3:test (default-test) @ kubernetes-quickstart --- [INFO] Tests are skipped. [INFO] [INFO] --- jar:3.4.1:jar (default-jar) @ kubernetes-quickstart --- [INFO] Building jar: /mnt/mysharedfolder/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar [INFO] [INFO] --- quarkus:3.25.2:build (default) @ kubernetes-quickstart --- [INFO] [io.quarkus.kubernetes.deployment.PropertyUtil] Kubernetes manifests are generated with 'The container port http' having default value '8080'. The app and manifests will get out of sync if the property 'quarkus.http.port' is changed at runtime. [INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 19821ms [INFO] [INFO] --- failsafe:3.5.3:integration-test (default) @ kubernetes-quickstart --- [INFO] Tests are skipped. [INFO] [INFO] --- quarkus:3.25.2:native-image-agent (default) @ kubernetes-quickstart --- [INFO] Missing native-image-agent-base-config directory with native image agent configuration to transform [INFO] [INFO] --- failsafe:3.5.3:verify (default) @ kubernetes-quickstart --- [INFO] Tests are skipped. [INFO] [INFO] --- install:3.1.2:install (default-install) @ kubernetes-quickstart --- [INFO] Installing /mnt/mysharedfolder/kubernetes-quickstart/pom.xml to /home/vagrant/.m2/repository/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/kubernetes-quickstart-1.0.0-SNAPSHOT.pom [INFO] Installing /mnt/mysharedfolder/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar to /home/vagrant/.m2/repository/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/kubernetes-quickstart-1.0.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 34.655 s [INFO] Finished at: 2025-11-06T14:28:16Z [INFO] ------------------------------------------------------------------------
Below, you can see the content of the target/kubernetes/kubernetes.yml Kubernetes manifests, provided by the Quarkus project packaging:
[in bold, I highlighted the changes with regard to remote development mode]
--- apiVersion: v1 kind: Service metadata: annotations: app.quarkus.io/quarkus-version: 3.25.2 app.quarkus.io/build-timestamp: 2025-11-06 - 14:27:59 +0000 labels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT app.kubernetes.io/managed-by: quarkus name: kubernetes-quickstart namespace: nl-amis-development spec: ports: - name: ports nodePort: 30010 port: 8180 protocol: TCP targetPort: 8080 selector: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: annotations: app.quarkus.io/quarkus-version: 3.25.2 app.quarkus.io/build-timestamp: 2025-11-06 - 14:27:59 +0000 labels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT app.kubernetes.io/managed-by: quarkus name: kubernetes-quickstart namespace: nl-amis-development spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT template: metadata: annotations: app.quarkus.io/quarkus-version: 3.25.2 app.quarkus.io/build-timestamp: 2025-11-06 - 14:27:59 +0000 labels: app.kubernetes.io/managed-by: quarkus app.kubernetes.io/name: kubernetes-quickstart app.kubernetes.io/version: 1.0.0-SNAPSHOT spec: containers: - env: - name: KUBERNETES_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: QUARKUS_LAUNCH_DEVMODE value: "true" image: localhost:8443/quarkus/kubernetes-quickstart:1.0.0-SNAPSHOT imagePullPolicy: Always name: kubernetes-quickstart ports: - containerPort: 8080 name: ports protocol: TCP
Build and push a container image for my project
Next, in order to build and push a container image for my project, I used the following commands on the Linux Command Prompt:
cd /mnt/mysharedfolder/kubernetes-quickstart mvn clean install -DskipTests -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true
With the following output:
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called WARNING: sun.misc.Unsafe::staticFieldBase has been called by com.google.inject.internal.aop.HiddenClassDefiner (file:/opt/apache-maven-3.9.11/lib/guice-5.1.0-classes.jar) WARNING: Please consider reporting this to the maintainers of class com.google.inject.internal.aop.HiddenClassDefiner WARNING: sun.misc.Unsafe::staticFieldBase will be removed in a future release [INFO] Scanning for projects... [INFO] [INFO] -------------------< org.acme:kubernetes-quickstart >------------------- [INFO] Building kubernetes-quickstart 1.0.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- clean:3.2.0:clean (default-clean) @ kubernetes-quickstart --- [INFO] Deleting /mnt/mysharedfolder/kubernetes-quickstart/target [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ kubernetes-quickstart --- [INFO] Copying 1 resource from src/main/resources to target/classes [INFO] [INFO] --- quarkus:3.25.2:generate-code (default) @ kubernetes-quickstart --- [INFO] [INFO] --- compiler:3.14.0:compile (default-compile) @ kubernetes-quickstart --- [INFO] Recompiling the module because of changed source code. [INFO] Compiling 1 source file with javac [debug parameters release 21] to target/classes [INFO] [INFO] --- quarkus:3.25.2:generate-code-tests (default) @ kubernetes-quickstart --- [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ kubernetes-quickstart --- [INFO] skip non existing resourceDirectory /mnt/mysharedfolder/kubernetes-quickstart/src/test/resources [INFO] [INFO] --- compiler:3.14.0:testCompile (default-testCompile) @ kubernetes-quickstart --- [INFO] Recompiling the module because of changed dependency. [INFO] Compiling 2 source files with javac [debug parameters release 21] to target/test-classes [INFO] [INFO] --- surefire:3.5.3:test (default-test) @ kubernetes-quickstart --- [INFO] Tests are skipped. [INFO] [INFO] --- jar:3.4.1:jar (default-jar) @ kubernetes-quickstart --- [INFO] Building jar: /mnt/mysharedfolder/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar [INFO] [INFO] --- quarkus:3.25.2:build (default) @ kubernetes-quickstart --- [INFO] [io.quarkus.kubernetes.deployment.PropertyUtil] Kubernetes manifests are generated with 'The container port http' having default value '8080'. The app and manifests will get out of sync if the property 'quarkus.http.port' is changed at runtime. [INFO] [io.quarkus.container.image.jib.deployment.JibProcessor] Starting (local) container image build for jar using jib. [WARNING] [io.quarkus.container.image.jib.deployment.JibProcessor] Base image 'registry.access.redhat.com/ubi9/openjdk-21-runtime:1.21' does not use a specific image digest - build may not be reproducible [INFO] [io.quarkus.container.image.jib.deployment.JibProcessor] Using base image with digest: sha256:360822c35c5741f542ab78fe123e6c4d9b68e0113a88d6e0250bb1f377b17f29 [INFO] [io.quarkus.container.image.jib.deployment.JibProcessor] Container entrypoint set to [/opt/jboss/container/java/run/run-java.sh] [INFO] [io.quarkus.container.image.jib.deployment.JibProcessor] Pushed container image localhost:8443/quarkus/kubernetes-quickstart:1.0.0-SNAPSHOT (sha256:40007537d5ad6078cedf8cf925d8544329d79ecfab2945245cb3a68f24eeaf8d) [INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 46173ms [INFO] [INFO] --- failsafe:3.5.3:integration-test (default) @ kubernetes-quickstart --- [INFO] Tests are skipped. [INFO] [INFO] --- quarkus:3.25.2:native-image-agent (default) @ kubernetes-quickstart --- [INFO] Missing native-image-agent-base-config directory with native image agent configuration to transform [INFO] [INFO] --- failsafe:3.5.3:verify (default) @ kubernetes-quickstart --- [INFO] Tests are skipped. [INFO] [INFO] --- install:3.1.2:install (default-install) @ kubernetes-quickstart --- [INFO] Installing /mnt/mysharedfolder/kubernetes-quickstart/pom.xml to /home/vagrant/.m2/repository/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/kubernetes-quickstart-1.0.0-SNAPSHOT.pom [INFO] Installing /mnt/mysharedfolder/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar to /home/vagrant/.m2/repository/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/kubernetes-quickstart-1.0.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 57.813 s [INFO] Finished at: 2025-11-06T14:31:15Z [INFO] ------------------------------------------------------------------------
Removing the created Kubernetes objects
So, as I mentioned in my previous article, the Quarkus generated manifest kubernetes.yml, was already applied before to the Kubernetes cluster and created the following Kubernetes objects (in my custom nl-amis-development namespace):
- Service
- Deployment
- Replica Set
- Pod
Because I wanted to create the Kubernetes objects again, first I had to delete the existing ones. I repeated some of the steps I already described in a previous article.
[Quarkus – Kubernetes extension (reinvestigated, part 4), implementing a Service of service type NodePort]
In order to delete the Replica Set and all of the dependent Pods (in the nl-amis-development namespace), I used the following command on the Linux Command Prompt:
kubectl delete -n nl-amis-development replicaset $(kubectl get replicasets -n nl-amis-development -o=jsonpath='{range .items..metadata}{.name}{"\n"}{end}' | grep kubernetes-quickstart- | awk '{print $1}')
With the following output:
replicaset.apps "kubernetes-quickstart-dcd557cfd" deleted
To delete a ReplicaSet and all of its Pods, use kubectl delete. The Garbage collector automatically deletes all of the dependent Pods by default.
[https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/#deleting-a-replicaset-and-its-pods]
In order to delete the Deployment, I used the following command on the Linux Command Prompt:
kubectl delete -n nl-amis-development deployment kubernetes-quickstart
With the following output:
deployment.apps "kubernetes-quickstart" deleted
In order to delete the Service, I used the following command on the Linux Command Prompt:
kubectl delete -n nl-amis-development service kubernetes-quickstart
With the following output:
service "kubernetes-quickstart" deleted
Recreating the Kubernetes objects in the nl-amis-development namespace, including a service with service type NodePort
Next, in order to recreate the Kubernetes manifests (in the nl-amis-development namespace), I used the following commands on the Linux Command Prompt:
cd /mnt/mysharedfolder/kubernetes-quickstart kubectl apply -f target/kubernetes/kubernetes.yml
With the following output:
service/kubernetes-quickstart created deployment.apps/kubernetes-quickstart created
Remark:
Be aware that I already created the nl-amis-development namespace object.
Then, I quickly checked whether the Pods were running successfully, via a series of command on the Linux Command Prompt.
kubectl get services --all-namespaces
With the following output:
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 85d kube-system kube-dns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP,9153/TCP 85d kube-system metrics-server ClusterIP 10.43.45.122 <none> 443/TCP 85d kube-system traefik LoadBalancer 10.43.141.14 10.0.2.15 80:30268/TCP,443:32611/TCP 85d kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.43.18.175 <none> 8000/TCP 85d kubernetes-dashboard kubernetes-dashboard ClusterIP 10.43.77.188 <none> 443/TCP 85d nl-amis-development kubernetes-quickstart NodePort 10.43.109.8 <none> 8180:30010/TCP 10s
kubectl get replicasets --all-namespaces
With the following output:
NAMESPACE NAME DESIRED CURRENT READY AGE kube-system coredns-5688667fd4 1 1 1 85d kube-system local-path-provisioner-774c6665dc 1 1 1 85d kube-system metrics-server-6f4c6675d5 1 1 1 85d kube-system traefik-c98fdf6fb 1 1 1 85d kubernetes-dashboard dashboard-metrics-scraper-749c668b7f 1 1 1 85d kubernetes-dashboard kubernetes-dashboard-76b75d676c 1 1 1 85d nl-amis-development kubernetes-quickstart-8579c4797d 1 1 1 42s
kubectl get daemonset --all-namespaces
With the following output:
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system svclb-traefik-dee09411 1 1 1 1 1 <none> 85d
kubectl get pods --all-namespaces
With the following output:
NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-5688667fd4-2hqfj 1/1 Running 31 (3h25m ago) 85d kube-system helm-install-traefik-crd-kp2hl 0/1 Completed 0 85d kube-system helm-install-traefik-vl7x8 0/1 Completed 2 85d kube-system local-path-provisioner-774c6665dc-2b9pq 1/1 Running 19 (3h25m ago) 85d kube-system metrics-server-6f4c6675d5-lljlv 1/1 Running 29 (3h25m ago) 85d kube-system svclb-traefik-dee09411-c7lzh 2/2 Running 38 (3h25m ago) 85d kube-system traefik-c98fdf6fb-stkt7 1/1 Running 28 (3h25m ago) 85d kubernetes-dashboard dashboard-metrics-scraper-749c668b7f-s7rjt 1/1 Running 19 (3h25m ago) 85d kubernetes-dashboard kubernetes-dashboard-76b75d676c-tq8fk 1/1 Running 24 (3h25m ago) 85d nl-amis-development kubernetes-quickstart-8579c4797d-5bc2b 1/1 Running 0 81s
kubectl get endpoints --all-namespaces
With the following output:
Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice NAMESPACE NAME ENDPOINTS AGE default kubernetes 10.0.2.15:6443 85d kube-system kube-dns 10.42.0.237:53,10.42.0.237:53,10.42.0.237:9153 85d kube-system metrics-server 10.42.0.234:10250 85d kube-system traefik 10.42.0.233:8000,10.42.0.233:8443 85d kubernetes-dashboard dashboard-metrics-scraper 10.42.0.232:8000 85d kubernetes-dashboard kubernetes-dashboard 10.42.0.236:8443 85d nl-amis-development kubernetes-quickstart 10.42.0.240:8080 104s
kubectl get endpoints -n nl-amis-development --output json
With the following output:
Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "Endpoints",
"metadata": {
"annotations": {
"endpoints.kubernetes.io/last-change-trigger-time": "2025-11-06T14:33:26Z"
},
"creationTimestamp": "2025-11-06T14:33:25Z",
"labels": {
"app.kubernetes.io/managed-by": "quarkus",
"app.kubernetes.io/name": "kubernetes-quickstart",
"app.kubernetes.io/version": "1.0.0-SNAPSHOT",
"endpoints.kubernetes.io/managed-by": "endpoint-controller"
},
"name": "kubernetes-quickstart",
"namespace": "nl-amis-development",
"resourceVersion": "38865",
"uid": "ecc05226-ce77-4c32-be16-e0f152d3084a"
},
"subsets": [
{
"addresses": [
{
"ip": "10.42.0.240",
"nodeName": "ubuntu2204.localdomain",
"targetRef": {
"kind": "Pod",
"name": "kubernetes-quickstart-8579c4797d-5bc2b",
"namespace": "nl-amis-development",
"uid": "fcb6b17c-0abc-446d-8292-53728092f0e4"
}
}
],
"ports": [
{
"name": "ports",
"port": 8080,
"protocol": "TCP"
}
]
}
]
}
],
"kind": "List",
"metadata": {
"resourceVersion": ""
}
}
kubectl get nodes
With the following output:
NAME STATUS ROLES AGE VERSION ubuntu2204.localdomain Ready control-plane,master 85d v1.33.3+k3s1
In order to determine the IP of the K3s node, I used the following commands on the Linux Command Prompt, as I described in a previous article:
[Creating a re-usable Vagrant Box from an existing VM with Ubuntu and k3s (with the Kubernetes Dashboard) and adding mysql, using Vagrant and Oracle VirtualBox]
nodeIP=$(kubectl get node ubuntu2204.localdomain -o yaml | grep address: | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}") echo "---$nodeIP---"
With the following output:
---10.0.2.15---
In order to determine the nodePort of the K3s node, I used the following commands on the Linux Command Prompt, as I described in a previous article:
[Quarkus – Kubernetes extension (reinvestigated, part 5), implementing a Service of service type LoadBalancer with K3s]
nodePort=$(kubectl get service kubernetes-quickstart -n nl-amis-development -o yaml | grep nodePort: | grep -E -o "[0-9]{5}")
echo "---$nodePort---"
With the following output:
---30010---
Below, you see an overview of my Kubernetes cluster at this moment:
Printing the logs for my container
As the “Remote Development Mode guide” mentioned, when the application starts you should see the following line in the logs: Profile dev activated. Live Coding activated.
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
In order to print the logs for a container in a pod, I used the following command on the Linux Command Prompt:
[https://kubernetes.io/docs/reference/kubectl/generated/kubectl_logs/]
kubectl logs -n nl-amis-development kubernetes-quickstart-8579c4797d-5bc2b
With the following output:
INFO exec -a "java" java -XX:MaxRAMPercentage=80.0 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dquarkus.package.output-directory=${PWD} -cp "." -jar /home/jboss/quarkus-run.jar
INFO running in /home/jboss
Press [e] to edit command line args (currently ''), [h] for more options>
2025-11-06 14:33:30,786 INFO [io.qua.kub.dep.PropertyUtil] (build-14) Kubernetes manifests are generated with 'The container port http' having default value '8080'. The app and manifests will get out of sync if the property 'quarkus.http.port' is changed at runtime.
2025-11-06 14:33:30,823 WARN [io.qua.kub.dep.KubernetesProcessor] (build-6) No project was detected, skipping generation of kubernetes manifests!
2025-11-06 14:33:31,098 INFO [org.tes.DockerClientFactory] (build-15) Testcontainers version: 1.21.3
2025-11-06 14:33:31,376 INFO [org.tes.doc.DockerMachineClientProviderStrategy] (build-15) docker-machine executable was not found on PATH ([/usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin, /sbin, /bin])
2025-11-06 14:33:31,378 ERROR [org.tes.doc.DockerClientProviderStrategy] (build-15) Could not find a valid Docker environment. Please check configuration. Attempted configurations were:
UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException (Could not find unix domain socket). Root cause NoSuchFileException (/var/run/docker.sock)
DockerDesktopClientProviderStrategy: failed with exception NullPointerException (Cannot invoke "java.nio.file.Path.toString()" because the return value of "org.testcontainers.dockerclient.DockerDesktopClientProviderStrategy.getSocketPath()" is null)As no valid configuration was found, execution cannot continue.
See https://java.testcontainers.org/on_failure.html for more details.
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2025-11-06 14:33:33,171 INFO [io.quarkus] (Quarkus Main Thread) kubernetes-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.25.2) started in 6.580s. Listening on: http://0.0.0.0:8080
2025-11-06 14:33:33,172 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2025-11-06 14:33:33,173 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, compose, kubernetes, rest, smallrye-context-propagation, vertx]
So, indeed the profile dev was activated and also “Live Coding” was activated.
By the way, I opted to ignore the error about finding a valid Docker environment:
2025-11-06 14:33:31,378 ERROR [org.tes.doc.DockerClientProviderStrategy] (build-15) Could not find a valid Docker environment. Please check configuration. Attempted configurations were: UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException (Could not find unix domain socket). Root cause NoSuchFileException (/var/run/docker.sock) DockerDesktopClientProviderStrategy: failed with exception NullPointerException (Cannot invoke "java.nio.file.Path.toString()" because the return value of "org.testcontainers.dockerclient.DockerDesktopClientProviderStrategy.getSocketPath()" is null)As no valid configuration was found, execution cannot continue. See https://java.testcontainers.org/on_failure.html for more details.
Calling the application
In order to forward local port 8090 to port 30100 on the K3s node ($nodeIP), I used the following command on the Linux Command Prompt, as I described in a previous article:
[https://technology.amis.nl/2020/04/30/creating-a-re-usable-vagrant-box-from-an-existing-vm-with-ubuntu-and-k3s-with-the-kubernetes-dashboard-and-adding-mysql-using-vagrant-and-oracle-virtualbox/]
socat tcp-listen:8090,fork tcp:10.0.2.15:30010 &
With the following output:
Then, in the Web Browser on my Windows laptop, I entered the URL:
Next, I continued reading the “Remote Development Mode guide”.
Connecting the local agent to the remote host
Now you need to connect your local agent to the remote host, using the remote-dev command:
./mvnw quarkus:remote-dev -Dquarkus.live-reload.url=http://my-remote-host:8080
Now every time you refresh the browser you should see any changes you have made locally immediately visible in the remote app. This is done via an HTTP based long polling transport, that will synchronize your local workspace and the remote application via HTTP calls.
If you do not want to use the HTTP feature then you can simply run the remote-dev command without specifying the URL. In this mode the command will continuously rebuild the local application, so you can use an external tool such as odo or rsync to sync to the remote application.
[https://quarkus.io/guides/maven-tooling#remote-development-mode]
So, with remote development mode enabled, I used vagrant ssh to connect into the running VM from a second session.
In order to connect the local agent to the remote host, I used the following commands on the Linux Command Prompt:
cd /mnt/mysharedfolder/kubernetes-quickstart mvn quarkus:remote-dev -Dquarkus.live-reload.url=http://localhost:8090
Remark about quarkus.live-reload.url:
| Live reload property | Type | Default |
|---|---|---|
| quarkus.live-reload.url URL used to use to connect to the remote dev-mode application Environment variable: QUARKUS_LIVE_RELOAD_URL |
string |
[https://quarkus.io/guides/all-config]
By the way, I could have used the following command on the Linux Command Prompt, which also works:
mvn quarkus:remote-dev -Dquarkus.live-reload.url=http://10.0.2.15:30010
With the following output:
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called WARNING: sun.misc.Unsafe::staticFieldBase has been called by com.google.inject.internal.aop.HiddenClassDefiner (file:/opt/apache-maven-3.9.11/lib/guice-5.1.0-classes.jar) WARNING: Please consider reporting this to the maintainers of class com.google.inject.internal.aop.HiddenClassDefiner WARNING: sun.misc.Unsafe::staticFieldBase will be removed in a future release [INFO] Scanning for projects... [INFO] [INFO] -------------------< org.acme:kubernetes-quickstart >------------------- [INFO] Building kubernetes-quickstart 1.0.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- quarkus:3.25.2:remote-dev (default-cli) @ kubernetes-quickstart --- [INFO] Invoking resources:3.3.1:resources (default-resources) @ kubernetes-quickstart [INFO] Copying 1 resource from src/main/resources to target/classes [INFO] Invoking quarkus:3.25.2:generate-code (default) @ kubernetes-quickstart [INFO] Invoking compiler:3.14.0:compile (default-compile) @ kubernetes-quickstart [INFO] Nothing to compile - all classes are up to date. [INFO] Invoking resources:3.3.1:testResources (default-testResources) @ kubernetes-quickstart [INFO] skip non existing resourceDirectory /mnt/mysharedfolder/kubernetes-quickstart/src/test/resources [INFO] Invoking quarkus:3.25.2:generate-code-tests (default) @ kubernetes-quickstart [INFO] Invoking compiler:3.14.0:testCompile (default-testCompile) @ kubernetes-quickstart [INFO] Nothing to compile - all classes are up to date. Listening for transport dt_socket at address: 5005 2025-11-06 14:55:25,228 INFO [io.qua.kub.dep.PropertyUtil] (build-26) Kubernetes manifests are generated with 'The container port http' having default value '8080'. The app and manifests will get out of sync if the property 'quarkus.http.port' is changed at runtime. 2025-11-06 14:55:39,655 INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 16913ms 2025-11-06 14:55:49,253 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending app/kubernetes-quickstart-1.0.0-SNAPSHOT.jar 2025-11-06 14:55:49,263 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending quarkus-run.jar 2025-11-06 14:55:49,305 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending lib/deployment/appmodel.dat 2025-11-06 14:55:59,643 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Connected to remote server
Making a first change to the application code
On my Windows laptop in the IntelliJ IDEA I opened the source code of the GreetingResource class. As you may remember from a previous article, I had a shared folder available.
[Quarkus – Supersonic Subatomic Java – Get Started (reinvestigated)]
Below you can see the source code of the GreetingResource class:
package org.acme;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from Quarkus REST";
}
}
So, then I changed the return value to:
[in bold, I highlighted the changes]
return "Hello from Quarkus REST. Live Coding demo, change A.";
Next, I refreshed the Web Browser on my Windows laptop.
From the second SSH session, I looked at the output on the Linux Command Prompt:
2025-11-06 15:16:26,425 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Remote dev client thread) Restarting quarkus due to changes in GreetingResource.class. 2025-11-06 15:16:42,387 INFO [io.qua.dep.QuarkusAugmentor] (Remote dev client thread) Quarkus augmentation completed in 15958ms 2025-11-06 15:16:42,471 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Remote dev client thread) Live reload total time: 16.300s 2025-11-06 15:16:50,030 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending app/kubernetes-quickstart-1.0.0-SNAPSHOT.jar 2025-11-06 15:16:50,051 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending dev/app/org/acme/GreetingResource.class 2025-11-06 15:16:50,097 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending quarkus-run.jar 2025-11-06 15:16:50,784 ERROR [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Remote dev request failed: java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8090/dev at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1699) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301) at io.quarkus.vertx.http.deployment.devmode.HttpRemoteDevClient$Session.run(HttpRemoteDevClient.java:222) at java.base/java.lang.Thread.run(Thread.java:1447)
With the following output (after some time):
So the “Live Coding” was working. Changes to my local file were immediately available in my containerized environment 😊.
By the way, I opted to ignore the error about the remote dev request that failed, because despite this error the “Live Coding” was working:
2025-11-06 15:16:50,784 ERROR [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Remote dev request failed: java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8090/dev at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1699) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301) at io.quarkus.vertx.http.deployment.devmode.HttpRemoteDevClient$Session.run(HttpRemoteDevClient.java:222) at java.base/java.lang.Thread.run(Thread.java:1447)
The URL seems to be based on: <quarkus.live-reload.url>/dev
In the first SSH session, in order to print the logs for a container in a pod, I used the following command on the Linux Command Prompt:
[https://kubernetes.io/docs/reference/kubectl/generated/kubectl_logs/]
kubectl logs -n nl-amis-development kubernetes-quickstart-8579c4797d-5bc2b
With the following output:
2025-11-06 15:16:50,189 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-5) Restarting quarkus due to changes in GreetingResource.class. 2025-11-06 15:16:50,191 INFO [io.quarkus] (Quarkus Main Thread) kubernetes-quickstart stopped in 0.001s 2025-11-06 15:16:50,377 WARN [io.qua.kub.dep.KubernetesProcessor] (build-22) No project was detected, skipping generation of kubernetes manifests! 2025-11-06 15:16:50,425 INFO [org.tes.DockerClientFactory] (build-14) Testcontainers version: 1.21.3 2025-11-06 15:16:50,429 INFO [org.tes.doc.DockerMachineClientProviderStrategy] (build-14) docker-machine executable was not found on PATH ([/usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin, /sbin, /bin]) 2025-11-06 15:16:50,437 ERROR [org.tes.doc.DockerClientProviderStrategy] (build-14) Could not find a valid Docker environment. Please check configuration. Attempted configurations were: UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException (Could not find unix domain socket). Root cause NoSuchFileException (/var/run/docker.sock) DockerDesktopClientProviderStrategy: failed with exception NullPointerException (Cannot invoke "java.nio.file.Path.toString()" because the return value of "org.testcontainers.dockerclient.DockerDesktopClientProviderStrategy.getSocketPath()" is null)As no valid configuration was found, execution cannot continue. See https://java.testcontainers.org/on_failure.html for more details. [Error Occurred After Shutdown] __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2025-11-06 15:16:50,777 INFO [io.quarkus] (Quarkus Main Thread) kubernetes-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.25.2) started in 0.584s. Listening on: http://0.0.0.0:8080 2025-11-06 15:16:50,779 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated. 2025-11-06 15:16:50,781 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, compose, kubernetes, rest, smallrye-context-propagation, vertx] 2025-11-06 15:16:50,781 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-5) Live reload total time: 24.611s 2025-11-06 15:16:50,782 ERROR [io.qua.ver.htt.run.dev.RemoteSyncHandler] (vert.x-worker-thread-4) Connect failed: java.lang.InterruptedException at java.base/java.lang.Object.wait0(Native Method) at java.base/java.lang.Object.wait(Object.java:366) at io.quarkus.vertx.http.runtime.devmode.RemoteSyncHandler$3$1.call(RemoteSyncHandler.java:142) at io.quarkus.vertx.http.runtime.devmode.RemoteSyncHandler$3$1.call(RemoteSyncHandler.java:129) at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$4(ContextImpl.java:192) at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:270) at io.vertx.core.impl.ContextImpl$1.execute(ContextImpl.java:221) at io.vertx.core.impl.WorkerTask.run(WorkerTask.java:56) at io.vertx.core.impl.TaskQueue.run(TaskQueue.java:81) at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18) at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2651) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2630) at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1622) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1589) at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11) at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:1583)
Making a second change to the application code
Next, I changed the return value to:
[in bold, I highlighted the changes]
return "Hello from Quarkus REST. Live Coding demo, change B.";
Then, I refreshed the Web Browser on my Windows laptop.
From the second SSH session, I looked at the output on the Linux Command Prompt:
2025-11-06 15:22:34,406 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Remote dev client thread) Restarting quarkus due to changes in GreetingResource.class. 2025-11-06 15:22:50,855 INFO [io.qua.dep.QuarkusAugmentor] (Remote dev client thread) Quarkus augmentation completed in 16445ms 2025-11-06 15:22:50,941 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Remote dev client thread) Live reload total time: 16.748s 2025-11-06 15:22:59,161 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending app/kubernetes-quickstart-1.0.0-SNAPSHOT.jar 2025-11-06 15:22:59,184 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending dev/app/org/acme/GreetingResource.class 2025-11-06 15:22:59,190 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending quarkus-run.jar 2025-11-06 15:22:59,885 ERROR [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Remote dev request failed: java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8090/dev at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1699) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301) at io.quarkus.vertx.http.deployment.devmode.HttpRemoteDevClient$Session.run(HttpRemoteDevClient.java:222) at java.base/java.lang.Thread.run(Thread.java:1447)
With the following output (after some time):
Again the “Live Coding” was working. Changes to my local file were immediately available in my containerized environment.
In the first SSH session, in order to print the logs for a container in a pod, I used the following command on the Linux Command Prompt:
[https://kubernetes.io/docs/reference/kubectl/generated/kubectl_logs/]
kubectl logs -n nl-amis-development kubernetes-quickstart-8579c4797d-5bc2b
With the following output:
2025-11-06 15:22:59,247 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-8) Restarting quarkus due to changes in GreetingResource.class. 2025-11-06 15:22:59,250 INFO [io.quarkus] (Quarkus Main Thread) kubernetes-quickstart stopped in 0.001s 2025-11-06 15:22:59,469 WARN [io.qua.kub.dep.KubernetesProcessor] (build-9) No project was detected, skipping generation of kubernetes manifests! 2025-11-06 15:22:59,503 INFO [org.tes.DockerClientFactory] (build-25) Testcontainers version: 1.21.3 2025-11-06 15:22:59,511 INFO [org.tes.doc.DockerMachineClientProviderStrategy] (build-25) docker-machine executable was not found on PATH ([/usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin, /sbin, /bin]) 2025-11-06 15:22:59,511 ERROR [org.tes.doc.DockerClientProviderStrategy] (build-25) Could not find a valid Docker environment. Please check configuration. Attempted configurations were: UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException (Could not find unix domain socket). Root cause NoSuchFileException (/var/run/docker.sock) DockerDesktopClientProviderStrategy: failed with exception NullPointerException (Cannot invoke "java.nio.file.Path.toString()" because the return value of "org.testcontainers.dockerclient.DockerDesktopClientProviderStrategy.getSocketPath()" is null)As no valid configuration was found, execution cannot continue. See https://java.testcontainers.org/on_failure.html for more details. [Error Occurred After Shutdown] __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2025-11-06 15:22:59,877 INFO [io.quarkus] (Quarkus Main Thread) kubernetes-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.25.2) started in 0.626s. Listening on: http://0.0.0.0:8080 2025-11-06 15:22:59,878 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated. 2025-11-06 15:22:59,878 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, compose, kubernetes, rest, smallrye-context-propagation, vertx] 2025-11-06 15:22:59,879 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-8) Live reload total time: 25.688s 2025-11-06 15:22:59,882 ERROR [io.qua.ver.htt.run.dev.RemoteSyncHandler] (vert.x-worker-thread-7) Connect failed: java.lang.InterruptedException at java.base/java.lang.Object.wait0(Native Method) at java.base/java.lang.Object.wait(Object.java:366) at io.quarkus.vertx.http.runtime.devmode.RemoteSyncHandler$3$1.call(RemoteSyncHandler.java:142) at io.quarkus.vertx.http.runtime.devmode.RemoteSyncHandler$3$1.call(RemoteSyncHandler.java:129) at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$4(ContextImpl.java:192) at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:270) at io.vertx.core.impl.ContextImpl$1.execute(ContextImpl.java:221) at io.vertx.core.impl.WorkerTask.run(WorkerTask.java:56) at io.vertx.core.impl.TaskQueue.run(TaskQueue.java:81) at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18) at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2651) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2630) at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1622) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1589) at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11) at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:1583)
I did also try some other things, like adding an extra class to my application and making changes to the content of file application.properties. All of these were successfully picked up by the remote dev mode 😊.
Starting a shell to the running container
In the first SSH session, in order to start a shell to the running container, I used the following command on the Linux Command Prompt:
kubectl exec -it --namespace nl-amis-development kubernetes-quickstart-8579c4797d-5bc2b -- /bin/bash
With the following output:
[default@kubernetes-quickstart-8579c4797d-5bc2b jboss]$
Then, in the shell I executed a series of commands, among others, to navigate the directory structure:
pwd
With the following output:
/home/jboss
whoami
With the following output:
default
ls -latr
With the following output:
total 52 drwxr-xr-x 1 root root 4096 Jan 1 1970 .. drwxr-xr-x 1 root root 4096 Jan 1 1970 . drwxrwxrwx 1 default root 4096 Nov 6 14:30 app drwxrwxrwx 2 default root 4096 Nov 6 14:30 quarkus drwxrwxrwx 1 default root 4096 Nov 6 14:30 lib -rwxrwxrwx 1 default root 5486 Nov 6 14:30 quarkus-app-dependencies.txt drwxrwxrwx 1 default root 4096 Nov 6 14:33 dev -rw-rw-rw- 1 default root 722 Nov 6 15:22 quarkus-run.jar
cd app ls -latr
With the following output:
total 20 drwxr-xr-x 1 root root 4096 Jan 1 1970 .. drwxrwxrwx 1 default root 4096 Nov 6 14:30 . -rw-rw-rw- 1 default root 1304 Nov 6 15:22 kubernetes-quickstart-1.0.0-SNAPSHOT.jar
cd .. cd quarkus ls -latr
With the following output:
total 464 drwxr-xr-x 1 root root 4096 Jan 1 1970 .. -rw-rw-rw- 1 default root 10120 Nov 6 14:30 transformed-bytecode.jar -rw-rw-rw- 1 default root 398093 Nov 6 14:30 generated-bytecode.jar -rw-rw-rw- 1 default root 42144 Nov 6 14:30 quarkus-application.dat drwxrwxrwx 2 default root 4096 Nov 6 14:30 . -rw-rw-rw- 1 default root 208 Nov 6 14:30 build-system.properties
cd .. cd lib ls -latr
With the following output:
total 40 drwxr-xr-x 1 root root 4096 Jan 1 1970 .. drwxrwxrwx 2 default root 4096 Nov 6 14:30 boot drwxrwxrwx 2 default root 12288 Nov 6 14:30 main drwxrwxrwx 1 default root 4096 Nov 6 14:30 . drwxrwxrwx 1 default root 4096 Nov 6 14:30 deployment
cd .. cd dev ls -latr
With the following output:
total 16 drwxr-xr-x 1 root root 4096 Jan 1 1970 .. drwxrwxrwx 1 default root 4096 Nov 6 14:33 . drwxr-xr-x 3 default root 4096 Nov 6 14:55 app
cd app ls -latr
With the following output:
total 16 drwxrwxrwx 1 default root 4096 Nov 6 14:33 .. drwxr-xr-x 3 default root 4096 Nov 6 14:55 org -rw-r--r-- 1 default root 778 Nov 6 14:55 application.properties drwxr-xr-x 3 default root 4096 Nov 6 14:55 .
exit
vagrant@ubuntu2204:/mnt/mysharedfolder/kubernetes-quickstart$
This represents the following shared folder structure on Windows laptop:
C:\My\AMIS\MySharedFolder\kubernetes-quickstart\target\quarkus-app
Later on, in the first SSH, again I started a shell to the running container in the same manner as I did before.
Then, in the shell I executed the following commands:
cd dev/app/org/acme/ ls -latr
With the following output:
total 12 drwxr-xr-x 3 default root 4096 Nov 7 09:44 .. drwxr-xr-x 2 default root 4096 Nov 7 11:42 . -rw-r--r-- 1 default root 610 Nov 7 11:43 GreetingResource.class
Next, two more times, I made some changes to my local file, the source code of the GreetingResource class. Followed by a refresh of the Web Browser on my Windows laptop.
In the shell I executed the following command:
ls -latr
With the following output after that first change:
total 12 drwxr-xr-x 3 default root 4096 Nov 7 09:44 .. drwxr-xr-x 2 default root 4096 Nov 7 11:42 . -rw-r--r-- 1 default root 610 Nov 7 12:50 GreetingResource.class
ls -latr
This was the corresponding output on the Linux Command Prompt, from the second SSH session:
2025-11-07 12:50:55,804 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending dev/app/org/acme/GreetingResource.class
In the shell I executed the following command:
ls -latr
With the following output after that second change:
total 12 drwxr-xr-x 3 default root 4096 Nov 7 09:44 .. drwxr-xr-x 2 default root 4096 Nov 7 11:42 . -rw-r--r-- 1 default root 610 Nov 7 12:53 GreetingResource.class
This was the corresponding output on the Linux Command Prompt, from the second SSH session:
2025-11-07 12:53:07,403 INFO [io.qua.ver.htt.dep.dev.HttpRemoteDevClient] (Remote dev client thread) Sending dev/app/org/acme/GreetingResource.class
In the shell I executed the following command:
exit
vagrant@ubuntu2204:/mnt/mysharedfolder/kubernetes-quickstart$
This confirmed what was mentioned earlier in this article and stated in the documentation:
The act of refreshing the browser triggers a scan of the workspace, and if any changes are detected the Java files are compiled, and the application is redeployed, then your request is serviced by the redeployed application.
[https://quarkus.io/guides/maven-tooling#dev-mode]
To conclude this article, the “Live Coding” was working. Changes to my local file were immediately available in my containerized environment 😊.
In this article, you can read more about the steps I took to use “Live Coding” and the remote development mode, so that changes made to the local files of my Java application become immediately visible in that deployed Java application that is running in a container on a Kubernetes cluster in my already existing Linux demo environment, including Quarkus and K3s (a lightweight certified Kubernetes distribution) and setup via Vagrant.
Feel free, among my other articles on this subject, to read:
- “Quarkus – Supersonic Subatomic Java, trying out Quarkus guide “Quarkus – Kubernetes extension” (part 1)”, September 27, 2020
In this article, you can read more about the steps I took, trying out the Quarkus code guide “Quarkus – Kubernetes extension”, and more specific the steps related to using custom labels and annotations. - “Quarkus – Supersonic Subatomic Java, trying out some Quarkus code guides (part2)”, October 3, 2020
In this article, you can read more about the steps I took, trying out the Quarkus code guide “Quarkus – Kubernetes extension”, and more specific the steps related to customizing the namespace, the service account name, the number of replicas and the type of service. - “Quarkus – Supersonic Subatomic Java, trying out Quarkus guide “Quarkus – Kubernetes extension (part 3)”, October 10, 2020
In this article, you can read more about the steps I took, trying out the Quarkus code guide “Quarkus – Kubernetes extension”, and more specific the steps related the automatic deployment of the generated resources to a target platform, in my case K3s (lightweight certified Kubernetes distribution).
