DevContainers using IntelliJ

Vineet Saju
4 min readApr 1, 2024

--

Problem:

On a recent Java project I was working on I was tasked with upgrading a few libraries to their latest versions. After doing so, I ran all the tests which passed locally but ended up failing on the build server (AWS CodeBuild in this case). The logs were not very descriptive of the underlying problem so I needed a way to run the test(s) locally in debug mode on the same environment used by the build machine.

Replication:

In-order to replicate the issue on my laptop and be able to debug locally using IntelliJ, I decided to use DevContainers. VSCode has traditionally provided great integration support for this feature, however since I prefer using IntelliJ for larger codebases, I decided to explore Intellij IDEA’s support for DevContainers.

Usage:

More details on how to work with Development Containers (including the full specification), can be found here.

For my purpose, a folder at the root of my project called .devContainer. Within the folder I added a devcontainer.json file like below: -

{
"image": "public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:3.0",
"mounts": [
"source=/Users/xxx/.m2/settings.xml,target=/root/.m2/settings.xml,type=bind",
"source=/Users/xxx/.m2/settings-security.xml,target=/root/.m2/settings-security.xml,type=bind"
"source=/Users/xxxx/.aws/credentials,target=/root/.aws/credentials,type=bind"
],
"runArgs": ["--env-file","./devcontainer.env"],
"postCreateCommand": "echo 'test'"
}

image refers to the public docker image that AWS Codebuild uses on top of which the build is run.

mounts refers to the locations of the files I want to make available from my machine to the destination within the docker container.

runArgs An array of Docker CLI arguments that should be used when running the container.

postCreateCommand: Any commands that need to be run post creation of the docker container. This can include scripts.

In my case, I needed to run several post create commands, which did not seem to run when using the postCreateCommand above. I believe this might be because the default entry point that comes with the AWS CodeBuild docker image was not getting overridden. While reading the docs I noticed that it was an option to use a DockerFile and override the default entrypoint with a custom one.

# Use the AWS Codebuild image as a base image
FROM public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:3.0
LABEL authors="Vineet Saju"

# For IntelliJ IDEA
WORKDIR /IdeaProjects/WLDA

# Copy the custom docker entrypoint file to the root of the container
COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh

# Configure aws creds
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials

# Set the entrypoint
ENTRYPOINT [ "/docker-entrypoint.sh" ]

# To ensure container stays running after above is executed
CMD [ "sleep", "infinity" ]
#Custom entry point file to perform required setup for project

#!/usr/bin/env bash
echo "Working directory: ${PWD}"

source ./ci-cd/setup_java_11.sh
source ./ci-cd/mvn_setup.sh
./mvnw --version

./mvnw $MAVEN_CLI_OPTS clean compile

./mvnw $MAVEN_CLI_OPTS test

exec "$@"

The above custom entrypoint file performs the necessary installs and compilations required before my IDE can attach successfully to the container.

This is how the devcontainer folder within my project looked like once the above steps were completed.

Location of the devcontainer folder within the project root

Attaching to the container:

Once the above has been setup, the container can easily be started by right clicking on the devContainer.json file and then “mounting sources”

Doing so will create a Docker container (provided you have Docker setup and running locally), and mount the existing root folder under which the file is present (which is the entire project folder in this case)

Container creation and Option to Attach using a specified version of IntelliJ for running.

Clicking on Continue as shown above will result in a new IntelliJ window being opened with the project mounted within it.

I can now run and debug the code locally within IntelliJ all while running within the Docker environment we created.

Container logs can be easily viewed via Docker Desktop as shown below:-

Conclusion:-

Being able to run and debug code locally within a target environment of choice proved to be extremely beneficial in this case. Not only was I able to identify the root cause of why the test was failing but also enabled me to quickly test out and fix it and other related issues without having to put logging statements and run the build multiple times on AWS Codebuild (which would have proven expensive).

--

--