Creating development containers with devpack-for-spring

In a previous post, I demonstrated the creation of build-containers that may be used to build a specific application in an air-gapped environment, or in continuous integration pipelines for a faster execution, that is a result of copying all the pre-fetched dependencies into the build-container image.
The same build-container images may be used as development containers with Visual Studio Code, using the Microsoft Dev Containers extension. Installing this extension is a prerequisite for this exercise:

A good way to set up your development environment is through the devpack-for-spring setup command used in the previous blog-post. For this exercise, you need to install docker using APT. If you are using devpack-for-spring setup, please select docker.io. If you are manually setting up the environment, please run:
sudo apt update && sudo apt install docker.io
Creating a Dev Container for a Gradle application
Let us now try creating a build-container for a sample Gradle application and then use it as a dev container.
Step 1: Clone a sample Gradle project
git clone https://github.com/pushkarnk/helidon-hello && cd helidon-hello
Step 2: Create an input rockcraft.yaml
This is a critical step. A build container produced by the Rockcraft plugins is a chiseled container image. It cannot be used as-is with the Dev Container extension. For example, chiseled containers remove the root user. And Dev Containers need to run a vscode-server which needs root permissions for installation.
This is identified as an issue and a future rockcraft version should not need you to implement this workaround step.
As a workaround, we supply an input rockcraft.yaml and depend on the merge feature of Rockcraft plugins. The resulting YAML is a merger of the input and the default rockcraft.yaml generated by the Rockcraft plugins. Create a file named input-rockcraft.yaml in the project directory, with the following contents:
name: build-helidon-dev
base: ubuntu@24.04
environment:
JAVA_HOME: /usr/lib/jvm/java-21-openjdk-${CRAFT_ARCH_BUILD_FOR}
parts:
openjdk:
plugin: nil
stage-packages:
- openjdk-21-jdk-headless
source: .
after:
- dependencies
override-build: |
craftctl default
dependencies:
plugin: nil
override-build: |
craftctl default
ubuntu@24.04 as the base is another critical requirement.Step 3: Update the build.gradle
Configure the rockcraft plugin and configure the input rockcraft yaml created in the previous step.
plugins {
id 'java'
id 'application'
id 'io.github.rockcrafters.rockcraft' version '1.2.1'
}
buildRockcraft {
rockcraftYaml = "input-rockcraft.yaml"
}
Step 4: Create the build container
Using devpack-for-spring we create a build container image for the sample application. This step also copies it as a docker image to the local docker daemon.
devpack-for-spring plugin rockcraft push-build-rock
The docker image must be listed by docker image ls
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
build-helidon-hello-dev 1.0.0 2a69adb0aa35 5 weeks ago 557MB
build-helidon-hello-dev latest 2a69adb0aa35 5 weeks ago 557MB
Step 5: Create the devcontainer.json file
Create a hidden file named .devcontainer.json in the project. The image key should have the name of the build container image.
{
"image": "build-helidon-hello-dev:latest",
"containerUser": "ubuntu"
}
Step 6: Rebuild and reopen in container
In VS Code, press CTRL+SHIFT+P and enter Dev Containers: Rebuild and Reopen in Container in the search bar:

This should open the project within the container.
Step 7: Iterate
The extension returns a prompt into the container. You can now make changes to the project in VS Code and run gradle build within the container. The application running inside the container must be reachable through the host.
Please refer to this quick demo video, for a visual reiteration of the above steps.
Conclusion
Development containers offer the luxury of the developing and testing the applications in an environment that is very close to that in which they would be eventually deployed.
Rockcraft build container images, if not chiseled, may be used as development containers in VS Code along with the Dev Containers extension. Even if we continue to keep them chiseled, adding the root user might help make the experience more seamless. This should be addressed in a future version of the Rockcraft plugins and the devpack-for-spring.




