Automate Spring Boot Docker Deployments with GitLab CI: A Step‑by‑Step Guide
This article walks through setting up GitLab CI to automatically build a Spring Boot JAR, create Docker images for Java 8 and Java 11, push them to a private registry, and deploy them to a server, covering required Dockerfiles, .gitlab-ci.yml configuration, environment files, and necessary GitLab variables.
Introduction
Docker and Spring Boot are a popular combination. This guide shows how to leverage GitLab CI to automatically build, push, and run Docker images for a Spring Boot application on a target server.
GitLab CI Overview
GitLab CI/CD is part of GitLab. Whenever developers push code to a repository, GitLab runs pipelines that build, test, and store the latest changes in the defined environment.
Why Choose GitLab CI Over Jenkins
Both tools are powerful, but GitLab CI is tightly integrated with the repository, requires no separate installation, and offers built‑in Docker support, a private container registry, and generous free build minutes.
Prerequisites
You have pushed a Spring Boot project to GitLab.
Docker is installed on the application server.
A Docker image registry (Docker Hub in this guide) is available.
An SSH RSA key pair has been generated on each server.
What You Will Create
You will create a Dockerfile and a .gitlab-ci.yml file that automate the following steps:
Build the application JAR.
Build a Docker image.
Push the image to a Docker registry.
Run the image on the application server.
Basic Project Information
The Spring Boot application is generated with Spring Initializr as a Maven project targeting Java 8 or Java 11.
Dockerfile
The Dockerfile used in the pipeline is:
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 Version Impact
From a Docker perspective, Java 8 images are significantly smaller and faster to build than Java 11 images. Approximate build times and image sizes observed:
Java 8 – build time ~4 minutes, image size ~180 MB.
Java 11 – build time ~14 minutes, image size ~480 MB.
These numbers may vary in real environments.
Dynamic ENTRYPOINT
To make the active Spring profile configurable, replace the static ENTRYPOINT with:
ENTRYPOINT [ "java", "-Dspring.profiles.active=$SPRING_ACTIVE_PROFILE", "-jar", "appdemo.jar" ]The SPRING_ACTIVE_PROFILE argument will be supplied via the .gitlab-ci.yml file.
.gitlab-ci.yml
The pipeline file defines three environments (development, QA, production) each represented by a Git branch and a corresponding .env file.
Environment Files
.develop.env .qa.env .master.envExample .develop.env:
export SPRING_ACTIVE_PROFILE='development'
export DOCKER_REPO='username/demo_app:dev'
export APP_NAME='demo_app_dev'
export PORT='8080'
export SERVER_IP='000.11.222.33'
export SERVER_SSH_KEY="$DEV_SSH_PRIVATE_KEY"Key Variables Explained
APP_NAME : Container name; must be set to avoid random naming.
PORT : Host port for the container.
SERVER_IP : IP of the target server (different per environment).
SERVER_SSH_KEY : Private SSH key stored as a GitLab CI variable.
GitLab CI Variables
In GitLab UI go to Settings → CI/CD → Variables and add:
DOCKER_USER – Docker Hub username.
DOCKER_PASSWORD – Docker Hub password.
ENV_SSH_PRIVATE_KEY – Private SSH key (including the BEGIN/END lines).
Pipeline Stages
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 *
StrictHostKeyChecking no" > ~/.ssh/config
- source .${CI_COMMIT_REF_NAME}.env
script:
- ssh root@$SERVER_IP "docker login -u $DOCKER_USER -p $DOCKER_PASSWORD docker.io; docker stop $APP_NAME; docker system prune -a -f; docker pull $DOCKER_REPO; docker run -d --name $APP_NAME -p $PORT:8080 -e SPRING_PROFILES_ACTIVE=$SPRING_ACTIVE_PROFILE $DOCKER_REPO; docker logout"The services entry enables Docker‑in‑Docker, allowing the pipeline to build and push images. Each stage runs sequentially: first the JAR is built, then the Docker image is built and pushed, and finally the image is deployed to the target server via SSH.
Deploy Step Details
The deploy job uses an Ubuntu image to install ssh-agent, add the private key, configure SSH, and execute a series of Docker commands on the remote server:
Stop the currently running container.
Remove all unused Docker images ( docker system prune -a -f).
Pull the newly built image from the registry.
Run the container with the appropriate name, port mapping, and active Spring profile.
Conclusion
This pipeline demonstrates a complete CI/CD workflow for a Spring Boot application: building the JAR, containerizing it with Docker, pushing the image to a private registry, and deploying it automatically to different environments using GitLab CI variables and environment‑specific .env files. Adjust the Java base image, registry, or server details as needed for your own projects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
