Recently I started looking at how I can leverage VS Code editor for Spring Boot and docker development for mainstream projects/applications. In this article I will try to cover subtle points that will get you started quickly.
TL;DR
- Install extension packs
- Configure Java runtimes in
settings.json
- Setup docker compose to pass
BUILD_ARGS
- Environment configuration for enabling remote debugging
Install Extension Packs
The starting part was relatively pretty easy, all you need is to install the following extensions —
- Extension Pack for Java
- Spring Boot Extension Pack
- Spring Boot Dashboard
- Lombok Annotations Support
- Docker
Configure Java Runtimes
If you are like me you might have projects using different JDKs. One of the ways I manage multiple JDKs on my machine is using SDKMAN. The problem I encountered with VS Code is you have to manually specify the path to various runtimes. You can achieve the same by editing the settings.json like so -
“java.configuration.runtimes”: [
{
“name”: “JavaSE-1.8”,
“path”: “$HOME/.sdkman/candidates/java/8.0.275.hs-adpt”
},
{
"name": "JavaSE-15",
"path": "$HOME/.sdkman/candidates/java/15.0.2.j9-adpt"
},
{
“name”: “JavaSE-11”,
“path”: “$HOME/.sdkman/candidates/java/11.0.14-zulu”,
“default”: true
}
]
Docker BUILD_ARGS
Moving on I realized that most of our Springboot applications are using the same DOCKERFILE and are using ARGS in them. Here is a sample of such a file —
FROM openjdk:11.0.12-jre-slim-bullseye
VOLUME /tmp
ARG JAR_FILE
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Duser.timezone=UTC", "-XshowSettings:vm", "-XX:+UseContainerSupport", "-jar", "-Xms2048M", "-XshowSettings:vm", "/app.jar"]
This is not so much related to VS Code, but I thought it might be helpful to the readers who might be running into similar issues where they want to build the docker image using docker-compose by simply running the following command —
docker compose up --build myApp -d
The alternative for this is a multi step process
$ docker compose build myApp --build-arg JAR_FILE=target/myApp.jar
$ docker compose up myApp
This works but is not as fluent. I tried few options and finally with some hit and trial I found the service definition that works like a charm. Here is the sample of docker compose service —
version: '3.2'
services:
myApp:
build:
context: ./myApp
args:
JAR_FILE: target/myApp.jar
ports:
- "8080:8080"
The above configuration is assuming you have a multi-module maven
/gradle
setup and myApp
is just one of the Spring Boot application.
Setting up VS Code for remote debugging
The last bit was to get the Spring Boot application running with debug port and have VS Code attach to the remote debugger. I was looking for a solution that was not obtrusive and did not want to manage multiple DOCKERFILE
s for the same project one for debugging and other for building images for production.
This was achieved by setting JAVA_TOOL_OPTION
environment variable in the docker-compose file itself like so —
version: '3.2'
services:
myApp:
build:
context: ./myApp
args:
JAR_FILE: target/myApp.jar
environment:
- JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,address=*:8081,server=y,suspend=n
ports:
- "8080:8080"
- "8081:8081"
Now when you bring up your application using docker compose up command you should see a log statement which will confirm you application will be able to receive remote connection on 8081 for remote debugging —
Picked up JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,address=*:8081,server=y,suspend=n
Listening for transport dt_socket at address: 8081
Next part was configuring VS code for attaching it to the remote debugger. This part was relatively easy. Add a new “Run and Debug” configuration like so —
{
"type": "java",
"name": "Remote MyApp Debug (attach)",
"request": "attach",
"hostName": "localhost",
"port": 8081
}
And Voila! you should be able to connect to the Spring Boot application running inside your container.
Happy Debugging!
Top comments (1)
I tried this, and it seemed to work: I could start my app in docker and connect to the debug server. But, I found that the breakpoints actually didn't work. No matter where I put a breakpoint, they get ignored and the app proceeds as if no breakpoint had been set.