VS Code setup for Spring Boot + Docker/Compose
Tags: java, springboot, vscode, docker
Published: 2022-04-15 17:32:14


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](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)
- [Spring Boot Extension Pack](https://marketplace.visualstudio.com/items?itemName=Pivotal.vscode-boot-dev-pack)
- [Spring Boot Dashboard](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-spring-boot-dashboard)
- [Lombok Annotations Support](https://marketplace.visualstudio.com/items?itemName=GabrielBB.vscode-lombok)
- [Docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-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](https://sdkman.io/). 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!