You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Clearly, SDKMAN was (originally) designed for interactive and personal use by a developer.
It can be used in a CI pipeline, but such use case under-documented. This is sad as SDKMAN is a great tool.
This ticket explores how SDKMAN can be used in such context and also what might be improved in SDKMAN (in code or documentation) to make such adoption easier.
CI docker image with SDKMAN
Many CI systems use Docker for execution and therefore require that you put your tools (e.g. SDKMAN) into a docker image. SDKMAN is both useful at build time (for installing software that we want included the image) as well as at execution time (to allow a CI pipeline to install additional software).
Putting SDKMAN into a Docker image for such purpose is in fact not that simple as there as many things to remember. Below is an example of how it might be done:
FROM ubuntu:22.04
# (1)SHELL ["/bin/bash", "-c"]
# (2) # Install needed packagesRUN apt-get update && apt-get install -y \
curl \
unzip \
&& rm -rf /var/lib/apt/lists/*
# (3)# Install SDKMAN RUN curl -s -S -o ./get-sdkman.sh "https://get.sdkman.io?rcupdate=false" \
&& chmod +x ./get-sdkman.sh \
&& ./get-sdkman.sh \
&& rm ./get-sdkman.sh \
# Change SDKMAN's config to be suitable for a CI pipeline execution
&& sed -i 's/sdkman_auto_answer=false/sdkman_auto_answer=true/g' $HOME/.sdkman/etc/config \
&& sed -i 's/sdkman_selfupdate_feature=true/sdkman_selfupdate_feature=false/g' $HOME/.sdkman/etc/config \
&& sed -i 's/sdkman_colour_enable=true/sdkman_colour_enable=false/g' $HOME/.sdkman/etc/config
# (4)ENV BASH_ENV="\$HOME/.sdkman/bin/sdkman-init.sh"# (5)ENTRYPOINT ["/bin/bash", "-c"]
Comments to Dockerfile:
SDKMAN requires Bash. The SHELL statement governs the shell used for subsequent RUN commands in the Dockerfile, not the shell used in the finished image.
I'm a bit uncertain about what packages SDKMAN requires. It is not documented, AFAIK. This is my guess.
Installing SDKMAN:
We use rcupdate=false as having SDKMAN manipulate .bashrc file is pointless for our use case. It wouldn't hurt, it would just be pointless.
There is no CI friendly install of SDKMAN so we have to manipulate the SDKMAN config file post installation.
SDKMAN needs to be in path and so on. This is taken care of by the sdkman-init-sh script. So far, so good. You can get SDKMAN to add this to .bashrc file but that file is only sourced for interactive logins. So for non-interactive logins you have to take care of this yourself. Using the BASH_ENV variable is one way to solve this problem. Notice the escaped $ character. This is important as we want the HOME variable to be resolved when the image is executed, not when it is built.
Make sure Bash is used.
You can of course use SDKMAN to install software in the docker image. The Dockerfile snippet can for example look like this (example installs Java 21):
RUN sdk install java 21.0.1-tem \
&& sdk flush
Notice how we execute sdk flush after the installation. This is in order to keep the size of the image as low as possible. It is crucial that the BASH_ENV variable is defined in the Dockerfile prior to attempting to use the sdk command in RUN statements. The Dockerfile ENV statement has effect both at build time and run time.
What might be improved in SDKMAN?
Here are some suggestions:
Suggestion 1
Have an install feature which creates a CI friendly config file, e.g. with
Clearly, SDKMAN was (originally) designed for interactive and personal use by a developer.
It can be used in a CI pipeline, but such use case under-documented. This is sad as SDKMAN is a great tool.
This ticket explores how SDKMAN can be used in such context and also what might be improved in SDKMAN (in code or documentation) to make such adoption easier.
CI docker image with SDKMAN
Many CI systems use Docker for execution and therefore require that you put your tools (e.g. SDKMAN) into a docker image. SDKMAN is both useful at build time (for installing software that we want included the image) as well as at execution time (to allow a CI pipeline to install additional software).
Putting SDKMAN into a Docker image for such purpose is in fact not that simple as there as many things to remember. Below is an example of how it might be done:
Comments to Dockerfile:
SHELL
statement governs the shell used for subsequentRUN
commands in the Dockerfile, not the shell used in the finished image.rcupdate=false
as having SDKMAN manipulate.bashrc
file is pointless for our use case. It wouldn't hurt, it would just be pointless.sdkman-init-sh
script. So far, so good. You can get SDKMAN to add this to.bashrc
file but that file is only sourced for interactive logins. So for non-interactive logins you have to take care of this yourself. Using theBASH_ENV
variable is one way to solve this problem. Notice the escaped$
character. This is important as we want theHOME
variable to be resolved when the image is executed, not when it is built.You can of course use SDKMAN to install software in the docker image. The Dockerfile snippet can for example look like this (example installs Java 21):
RUN sdk install java 21.0.1-tem \ && sdk flush
Notice how we execute
sdk flush
after the installation. This is in order to keep the size of the image as low as possible. It is crucial that theBASH_ENV
variable is defined in the Dockerfile prior to attempting to use thesdk
command inRUN
statements. The DockerfileENV
statement has effect both at build time and run time.What might be improved in SDKMAN?
Here are some suggestions:
Suggestion 1
Have an install feature which creates a CI friendly config file, e.g. with
Suggestion 2
Document what packages (e.g.
curl
, etc) that SDKMAN requires for its execution.Suggestion 3
Document how SDKMAN might be used in a
Dockerfile
. Have some examples in the documentation. This ticket is hopefully a good starting point.The text was updated successfully, but these errors were encountered: