Cloud Native 14 min read

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.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Automating Spring Boot Deployment with GitLab CI and Docker

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.

JavaDockerCI/CDDevOpsSpring BootGitLab CIDockerfile
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.