GitLab CI/CD Configuration Guide with .gitlab-ci.yml

Core Concepts of GitLab CI/CD

GitLab CI/CD is an integrated tool for implementing continuous software development practices:

  • Continuous Integration (CI): Automated building and testing of code changes upon each push.
  • Continuous Delivery (CD): Automated deployment with manual approval trigger.
  • Continuous Deployment (CD): Fully automated deployment without human intervention.

These practices minimize bugs by validating changes early and ensuring code standards before merging into main branches.

The CI/CD pipeline is defined in a .gitlab-ci.yml file placed in the repository root. GitLab Runner executes the scripts defined in this configuration file.

Pipeline Structure and Execution

When a .gitlab-ci.yml file exists in your repository, GitLab automatically detects it and triggers pipelines on code pushes. The GitLab Runner executes jobs defined in the file, similar to running commands in a terminal.

Basic pipeline example:

default:
  before_script:
    - apt-get update && apt-get install -y python3-pip

run_tests:
  script:
    - python3 --version
    - pip3 install -r requirements.txt
    - python3 -m pytest tests/

Creating a Basic .gitlab-ci.yml Configuration

Simple Ruby Project Example

image: "ruby:3.0"

preparation:
  before_script:
    - apt-get update -qq
    - apt-get install -y sqlite3 libsqlite3-dev nodejs
    - ruby -v
    - gem install bundler --no-document
    - bundle install --jobs $(nproc)

test_suite:
  script:
    - bundle exec rspec

code_analysis:
  script:
    - bundle exec rubocop

This configuration defines two jobs (test_suite and code_analysis) that share common preparation steps. The image directive specifies the Docker container to use for execution.

Registering and Starting GitLab Runner

# Download GitLab Runner
sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64

# Make it executable
sudo chmod +x /usr/local/bin/gitlab-runner

# Create system user
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

# Install as service
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner

# Register with your GitLab instance
sudo gitlab-runner register

# Start the runner service
sudo gitlab-runner start

During registration, you'll need your GitLab instance URL and registration token, found under Settings → CI/CD → Runners in you're project.

Multi-Stage Pipeline for Java Applications

Example configuration for a Spring Boot application with Docker deployment:

image: openjdk:11-jdk-slim

stages:
  - compile
  - test
  - package
  - deploy

cache:
  paths:
    - .m2/repository
    - target/

compile_code:
  stage: compile
  script:
    - ./mvnw compile

execute_tests:
  stage: test
  script:
    - ./mvnw test

create_artifact:
  stage: package
  script:
    - ./mvnw package -DskipTests
  artifacts:
    paths:
      - target/*.jar
    expire_in: 1 week

deploy_to_cloud:
  stage: deploy
  script:
    - curl -L "https://cli.example.com/stable?release=linux64-binary" | tar zx
    - ./cloud-cli login -u $CLOUD_USER -p $CLOUD_PASS -a api.cloudprovider.com
    - ./cloud-cli deploy
  only:
    - main

Advanced Docker-Based Pipeline

For complex projects with multiple services, you can use Docker Compose within your pipeline:

stages:
  - build_base
  - package_artifacts
  - run_services

build_base_image:
  stage: build_base
  script:
    - docker build -t java-build-env -f ./BaseDockerfile .
  tags:
    - docker-runner

compile_services:
  stage: package_artifacts
  script:
    - docker build -t maven-builder -f ./BuildDockerfile .
    - docker run -v $PWD/artifacts:/output maven-builder
    - docker build -t service-api -f ./api/Dockerfile .
    - docker build -t service-worker -f ./worker/Dockerfile .
  artifacts:
    paths:
      - artifacts/
  tags:
    - docker-runner

start_environment:
  stage: run_services
  script:
    - docker-compose up -d
  tags:
    - docker-runner
  only:
    - main

Dockerfile Examples for Java Services

Base Envirnoment Dockerfile

FROM centos:8

# Install Java
RUN yum install -y wget tar
RUN mkdir -p /opt/java
RUN wget -P /opt/java https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz
RUN tar -xzf /opt/java/openjdk-11.0.2_linux-x64_bin.tar.gz -C /opt/java

ENV JAVA_HOME /opt/java/jdk-11.0.2
ENV PATH $JAVA_HOME/bin:$PATH

# Install Maven
RUN wget -P /opt https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
RUN tar -xzf /opt/apache-maven-3.6.3-bin.tar.gz -C /opt
ENV M2_HOME /opt/apache-maven-3.6.3
ENV PATH $M2_HOME/bin:$PATH

Application Service Dockerfile

FROM openjdk:11-jre-slim

WORKDIR /app
COPY artifacts/service-app.jar /app/service-app.jar
RUN chmod +x /app/service-app.jar

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/service-app.jar"]

Docker Compose Configuration

version: '3.8'

services:
  web-service:
    image: service-api
    ports:
      - "8080:8080"
    restart: unless-stopped
    command: ["java", "-jar", "/app/service-app.jar"]

  background-worker:
    image: service-worker
    restart: unless-stopped
    command: ["java", "-jar", "/app/worker-app.jar"]

Environment Variables and Secrets

Store sensitive data like API keys and credentials in GitLab CI/CD variables (Settings → CI/CD → Variables):

deploy_production:
  stage: deploy
  script:
    - echo "Deploying to $DEPLOY_ENV"
    - ./deploy.sh --token $API_TOKEN --env $DEPLOY_ENV
  environment:
    name: production
    url: https://app.example.com
  only:
    - main

Artifacts and Caching

Optimize build times by caching dependencies and preserving build outputs:

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"

cache:
  key: "$CI_COMMIT_REF_SLUG"
  paths:
    - .m2/repository/
    - node_modules/
    - target/
  policy: pull-push

build_job:
  stage: build
  script:
    - mvn clean compile
  artifacts:
    paths:
      - target/classes/
      - target/*.jar
    reports:
      junit: target/surefire-reports/TEST-*.xml

Pipeline Visualization and Monitoring

View pipeline execution in GitLab under CI/CD → Pipelines. Monitor job logs, track execution time, and review test reports. Failed pipelines provide detailed error logs for debugging.

Troubleshooting Common Issues

Container Exits Immediately

Ensure your Docker containers have persistent processes. For Java applications, avoid using -d flag in ENTRYPOINT and ensure the JVM runs in foreground mode.

File Permission Problems

Set appropriate permissions in Dockerfile:

RUN chmod 755 /app/application.jar
USER 1001
ENTRYPOINT ["java", "-jar", "/app/application.jar"]

Build Context Path Issues

When copying files in Dockerfile, paths are relative to build context. Ensure proper directory structure:

# Correct: Copy from relative path in build context
COPY ./target/app.jar /app/app.jar

# Incorrect: Using absolute host paths
COPY /home/runner/build/app.jar /app/app.jar

Tags: gitlab CI/CD devops docker Continuous Integration

Posted on Mon, 18 May 2026 20:08:25 +0000 by andynick