Operations 15 min read

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.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Automate Spring Boot Docker Deployments with GitLab CI: A Step‑by‑Step Guide

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.env

Example .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.

GitLab CI variable setup
GitLab CI variable setup
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaDockerci/cdDeploymentSpring BootGitLab CIDockerfile
Code Ape Tech Column
Written by

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

0 followers
Reader feedback

How this landed with the community

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.