Automating Spring Boot Deployment with GitLab CI and Docker
This guide explains how to use GitLab CI to automatically build, push, and run Docker images for a Spring Boot application, covering Dockerfile creation, Java version considerations, environment variable management, and deployment steps across development, testing, and production environments.
Docker and Spring Boot are a popular combination; this article shows how to leverage GitLab CI to automatically build, push, and run Docker images for a Spring Boot application.
GitLab CI
GitLab CI/CD runs whenever code is pushed to a repository, building, testing, and storing changes in the required environment.
Key reasons to choose GitLab CI include ease of learning, maintainability, integration, being part of the GitLab repository, good Docker integration, a private container registry, and free monthly build minutes.
Why GitLab CI surpasses Jenkins
Both tools are powerful; GitLab CI is part of the repository, requires no separate installation, and needs minimal maintenance compared to setting up a dedicated Jenkins server.
Prerequisites for using GitLab CI
You have pushed a Spring Boot project to GitLab.
Docker is installed on the application server.
You have a Docker image registry (Docker Hub in this guide).
An SSH RSA key is generated on the server.
What you will create
A Dockerfile .
A .gitlab-ci.yml file.
These will automatically:
Build the application JAR.
Build the Docker image.
Push the image to the Docker repository.
Run the image on the application server.
Dockerfile
Example Dockerfile (Java 11 version shown; a Java 8 variant is commented):
FROM maven:3.6.3-jdk-11-slim AS MAVEN_BUILD
#FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD FOR JAVA 8
ARG SPRING_ACTIVE_PROFILE
MAINTAINER Jasmin
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn clean install -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE
FROM openjdk:11-slim
#FROM openjdk:8-alpine FOR JAVA 8
WORKDIR /app
COPY --from=MAVEN_BUILD /build/target/appdemo-*.jar /app/appdemo.jar
ENTRYPOINT ["java", "-jar", "appdemo.jar"]Java Versions
From a Docker perspective, Java 8 images are significantly smaller (≈180 MB, ~4 min build) than Java 11 images (≈480 MB, ~14 min build), leading to faster builds and deployments.
Docker Image
The size difference is mainly due to the base OpenJDK image used; Java 11 uses a larger, untested Alpine variant.
Dynamic Variables in ENTRYPOINT
To make the entrypoint dynamic, replace hard‑coded values with variables passed via ARG in .gitlab-ci.yml :
ENTRYPOINT [ "java", "-Dspring.profiles.active=$SPRING_ACTIVE_PROFILE", "-jar", "appdemo.jar" ].gitlab-ci.yml
The pipeline consists of three stages: build‑jar, build‑and‑push Docker image, and deploy.
services:
- docker:19.03.7-dind
stages:
- build jar
- build and push docker image
- deploy
build:
image: maven:3.6.3-jdk-11-slim
stage: build jar
before_script:
- source .${CI_COMMIT_REF_NAME}.env
script:
- mvn clean install -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE
artifacts:
paths:
- target/*.jar
docker build:
image: docker:stable
stage: build and push docker image
before_script:
- source .${CI_COMMIT_REF_NAME}.env
script:
- docker build --build-arg SPRING_ACTIVE_PROFILE=$SPRING_ACTIVE_PROFILE -t $DOCKER_REPO .
- docker login -u $DOCKER_USER -p $DOCKER_PASSWORD docker.io
- docker push $DOCKER_REPO
deploy:
image: ubuntu:latest
stage: deploy
before_script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d 'r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo -e "Host *\nStrictHostKeyChecking no" > ~/.ssh/config
- source .${CI_COMMIT_REF_NAME}.env
script:
- ssh root@$SERVER "docker stop $APP_NAME; docker system prune -a -f; docker pull $DOCKER_REPO; docker container run -d --name $APP_NAME -p $PORT:8080 -e SPRING_PROFILES_ACTIVE=$SPRING_ACTIVE_PROFILE $DOCKER_REPO"The services line enables Docker‑in‑Docker, allowing the pipeline to build and push images. The stages define the execution order. Each stage loads environment variables from branch‑specific .env files.
In the deploy stage, an Ubuntu image is used to SSH into the target server, stop any running container, clean up unused images, pull the new image, and run it with the appropriate environment variables.
Important Notes
APP_NAME names the container; without it Docker assigns a random name.
PORT defines the host port for the container.
SERVER_IP is the server’s IP address; each environment may have a different server.
SERVER_SSH_KEY holds the private SSH key stored as a GitLab variable.
By following this guide, you can automatically build, test, and deploy a Spring Boot application using GitLab CI, Docker, and environment‑specific configurations.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.