Using jlink and jdeps to build docker image#526
Conversation
rrobetti
left a comment
There was a problem hiding this comment.
@cunhazera this PR has to alter the https://github.com/Open-J-Proxy/ojp/blob/main/.github/workflows/main.yml
Specifically how the docker image is built and run for tests, steps:
Build OJP Server Docker image
Start OJP Server container
|
|
||
| # Step 1: Download open source JDBC drivers | ||
| echo -e "${GREEN}Step 1: Downloading open source JDBC drivers...${NC}" | ||
| bash "$SCRIPT_DIR/download-drivers.sh" "$SCRIPT_DIR/ojp-libs" |
There was a problem hiding this comment.
We should not download drivers in the script that builds the docker image. The script that builds the image only builds the image, nothing else. We no longer do "batteries included" approach. The user must add the drivers they want to use, the download-drivers.sh is just a helper.
There was a problem hiding this comment.
Pull request overview
This PR switches the ojp-server Docker image build from Jib to a multi-stage Dockerfile that uses jlink to produce a slimmer custom JRE, and adds an integration test to ensure the locally-built image starts successfully.
Changes:
- Add a multi-stage
ojp-server/Dockerfilethat builds a custom Alpine JRE viajlinkand runs the shaded server JAR. - Replace the Jib-based Maven Docker build with an
exec-maven-plugindocker buildinpre-integration-test, and add a Failsafe IT that starts the built image. - Update
ojp-serverDocker documentation and refactordocker-build.shto build/push using the new Dockerfile flow.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
ojp-server/src/test/java/org/openjproxy/grpc/server/OjpDockerImageIT.java |
New integration test that starts the locally-built Docker image via OjpContainer. |
ojp-server/README.md |
Documents the new Dockerfile-based build/push flow and how to verify via Maven. |
ojp-server/pom.xml |
Removes Jib config, adds Docker build execution, and configures Failsafe ITs with an image version property. |
ojp-server/Dockerfile |
New multi-stage Dockerfile using jlink to create a custom JRE and run the shaded JAR. |
ojp-server/docker-build.sh |
Reworked helper script to download drivers, build the shaded JAR, and docker build/docker push. |
| <!-- Docker image: build via Dockerfile (multi-stage jlink image) --> | ||
| <plugin> | ||
| <groupId>com.google.cloud.tools</groupId> | ||
| <artifactId>jib-maven-plugin</artifactId> | ||
| <version>${jib.plugin.version}</version> | ||
| <groupId>org.codehaus.mojo</groupId> | ||
| <artifactId>exec-maven-plugin</artifactId> | ||
| <version>3.1.0</version> |
| void localImageStartsSuccessfully() { | ||
| String version = System.getProperty("ojp.image.version"); | ||
| DockerImageName image = DockerImageName.parse("rrobetti/ojp:" + version) |
| ### Run locally | ||
|
|
||
| ```bash | ||
| docker run -p 1059:1059 rrobetti/ojp:0.4.17-SNAPSHOT |
| @@ -21,5 +39,12 @@ docker run -d \ | |||
| rrobetti/ojp:0.4.21-beta | |||
| ## Docker Image | ||
|
|
||
| ### Build docker image locally | ||
| The image is a custom Alpine JRE built with `jlink` (only the modules required by OJP), bringing the final image size to **128MB**. |
| COMMAND="${1:-build}" | ||
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" |
| # Step 4: Build Docker image | ||
| echo -e "${GREEN}Step 3: Building Docker image ${IMAGE}...${NC}" | ||
| docker build -t "$IMAGE" "$SCRIPT_DIR" | ||
|
|
||
| if [ $? -ne 0 ]; then | ||
| echo "" | ||
| echo -e "${RED}Failed to download drivers!${NC}" | ||
| echo -e "${RED}Docker build failed!${NC}" | ||
| exit 1 | ||
| fi |
…vers via download-drivers.sh
|
@cunhazera workflow failed, please check. |
|
@rrobetti pushed a new commit. |
Not good enough. On it. |
|
@rrobetti looks like an unrelated error happened. Can you please check? |
|
@cunhazera don't worry about [Main CI / notify-integration (pull_request)] this is expected as per branches should not trigger external framework integration tests, the relevant tests are all passing now. |
@rrobetti sorry, which comments are still left behind? I think I addressed all of them, but I think I'm missing something here. |
I just replaced jib in other workflows by docker commands. Will need some help to test it. |
| - name: Build OJP Server Docker image | ||
| run: mvn jib:dockerBuild -pl ojp-server -Dgpg.skip=true | ||
| run: | | ||
| VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout -pl ojp-server) |
There was a problem hiding this comment.
@cunhazera can't this version be some sort of a global variable? the same code to get it is present in a few places.
| ############################################################################## | ||
| # OJP Docker Build Helper | ||
| # | ||
| # This script automates the Docker image build process with open source |
There was a problem hiding this comment.
@cunhazera why did you remove all these comments? I found them usefull
| # Commands: | ||
| # build - Build Docker image locally (default) | ||
| # push - Build and push Docker image to registry (requires docker login) | ||
| # |
| # | ||
| ############################################################################## | ||
|
|
||
| set -e # Exit on error |
| set -e # Exit on error | ||
| set -e | ||
|
|
||
| # Color output |
| GREEN='\033[0;32m' | ||
| YELLOW='\033[1;33m' | ||
| BLUE='\033[0;34m' | ||
| NC='\033[0m' # No Color |
| NC='\033[0m' # No Color | ||
| NC='\033[0m' | ||
|
|
||
| # Default command |
| COPY ojp-libs/ /opt/ojp/ojp-libs/ | ||
| COPY target/ojp-server-*-shaded.jar /opt/ojp/ojp-server.jar | ||
|
|
||
| EXPOSE 1059 |
There was a problem hiding this comment.
@cunhazera what about the prometheus port 9159 ? Also the ports can be configured in OJP server, how can we handle that ? https://github.com/Open-J-Proxy/ojp/blob/main/documents/configuration/ojp-server-configuration.md
There was a problem hiding this comment.
What I suggest: defaulting these values with the possibility to override them via -e in docker run.
That handles the users the responsibility to sync all the config values.
Now I think we should figure out if reducing the image size (what this PR accomplishes) is worthy, considering that our image generation strategy is changing drastically and also giving users one more step to set things up.
|
@cunhazera apologies, forgot to submit the comments, they are visible now. |
… var for version in workflow
|
|
@rrobetti thanks for these comments! The new commit should address all of them! |
| COPY ojp-libs/ /opt/ojp/ojp-libs/ | ||
| COPY target/ojp-server-*-shaded.jar /opt/ojp/ojp-server.jar | ||
|
|
||
| EXPOSE ${OJP_SERVER_PORT} ${OJP_PROMETHEUS_PORT} |
There was a problem hiding this comment.
@cunhazera we do not really need this right? can we remove EXPOSE and the variables entirelly? K8S for example ignores EXPOSE anyway.
The operator will define the ports via docker run command
| # the image metadata will always list 1059 and 9159 regardless of what is | ||
| # passed at runtime. When overriding ports, the -p mapping must match the | ||
| # -e value — Docker does not update EXPOSE dynamically. | ||
| ENV OJP_SERVER_PORT=1059 |
There was a problem hiding this comment.
@cunhazera if we remove EXPOSE, these variables are no longer needed. The application will set these defaults, there is no need to do it here. I am leaning towards removing from here to simplify.
|
|
||
| # Stage 2: Runtime image | ||
| FROM alpine:3.21 | ||
|
|
There was a problem hiding this comment.
@cunhazera add a user to run OJP, currently running as root.
RUN addgroup -S ojp && adduser -S ojp -G ojp
| ENV JAVA_HOME=/opt/java | ||
| ENV PATH="${JAVA_HOME}/bin:${PATH}" | ||
|
|
||
| # Default ports for the gRPC server and Prometheus metrics endpoint. |
There was a problem hiding this comment.
@cunhazera we can remove this comment if the variables are removed.
| # -e value — Docker does not update EXPOSE dynamically. | ||
| ENV OJP_SERVER_PORT=1059 | ||
| ENV OJP_PROMETHEUS_PORT=9159 | ||
|
|
There was a problem hiding this comment.
@cunhazera to run as ojp user we need
ENV JAVA_HOME=/opt/java
ENV PATH="${JAVA_HOME}/bin:${PATH}"
| COPY target/ojp-server-*-shaded.jar /opt/ojp/ojp-server.jar | ||
|
|
||
| EXPOSE ${OJP_SERVER_PORT} ${OJP_PROMETHEUS_PORT} | ||
|
|
|
@cunhazera please check my latest comments, I know I increased the scope of this PR a little by asking you to change to use a ojp user instead of root, but I believe it is a small change that delivers production operational grade level, so please add the change. |
Sure, they all make sense. |



No description provided.