Gitlab Pipeline – services – What is services in GitLab CI/CD?

DevOps

MOTOSHARE 🚗🏍️
Turning Idle Vehicles into Shared Rides & Earnings

From Idle to Income. From Parked to Purpose.
Earn by Sharing, Ride by Renting.
Where Owners Earn, Riders Move.
Owners Earn. Riders Move. Motoshare Connects.

With Motoshare, every parked vehicle finds a purpose. Owners earn. Renters ride.
🚀 Everyone wins.

Start Your Journey with Motoshare

The services keyword in GitLab CI/CD allows you to run additional Docker containers alongside the main Docker container for your job. These service containers typically provide dependencies that your job needs during its execution, such as a database (like PostgreSQL, MySQL), a caching service (like Redis), or any other network-accessible service.

The main job container can then connect to these service containers over the network.


Example .gitlab-ci.yml with services:

This example will use a PostgreSQL database as a service for a job that needs to interact with it.

YAML

# .gitlab-ci.yml

stages:
  - test

# Job that needs a PostgreSQL database
integration_test_with_db:
  stage: test
  image: alpine:latest # A lightweight image for the main job

  variables:
    # These variables are used by the job to connect to the PostgreSQL service.
    # They match the ones used by the PostgreSQL service itself.
    DB_USER: "testuser"
    DB_PASSWORD: "testpassword"
    DB_NAME: "testdb"
    DB_HOST: "postgres" # Default hostname for the service (derived from image name)

  services:
    - name: postgres:14-alpine # Specifies the Docker image for the PostgreSQL service
      alias: db-server # Optional: A custom hostname alias for this service
      command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] # Optional: Custom command for the service
      variables:
        # Environment variables for the PostgreSQL service container itself
        POSTGRES_USER: $DB_USER # Use the job-level variable
        POSTGRES_PASSWORD: $DB_PASSWORD
        POSTGRES_DB: $DB_NAME
        # For faster startup in CI, not recommended for production PG
        POSTGRES_HOST_AUTH_METHOD: "trust"

  before_script:
    - echo "Installing PostgreSQL client in the main job container..."
    - apk update
    - apk add --no-cache postgresql14-client # Install psql client for version 14

  script:
    - echo "--- Running Integration Tests ---"
    - echo "Waiting for PostgreSQL service to be ready..."
    # GitLab CI generally waits for services to be ready, but a small sleep or retry loop might be needed in complex cases.
    # For PostgreSQL, the service itself takes a moment to initialize the database.
    - sleep 15 # Give PostgreSQL a bit more time to initialize fully

    - echo "Attempting to connect to PostgreSQL service at host: $DB_HOST (or alias 'db-server')"

    # Test connection using the default service name 'postgres' as hostname
    - PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "SELECT version();"
    - PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "CREATE TABLE IF NOT EXISTS  my_table (id SERIAL PRIMARY KEY, data VARCHAR(100));"
    - PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "INSERT INTO my_table (data) VALUES ('Hello from GitLab CI via default service name!');"

    # Test connection using the alias 'db-server'
    - PGPASSWORD=$DB_PASSWORD psql -h db-server -U $DB_USER -d $DB_NAME -c "INSERT INTO my_table (data) VALUES ('Hello from GitLab CI via alias!');"
    - PGPASSWORD=$DB_PASSWORD psql -h db-server -U $DB_USER -d $DB_NAME -c "SELECT * FROM my_table;"

    - echo "Integration tests requiring database would run here."
Code language: PHP (php)

Explanation:

  1. services: Keyword:
    • This keyword is defined at the job level (e.g., within integration_test_with_db).
    • It takes a list of service definitions. Each service runs in its own Docker container, linked to the main job’s container.
  2. Service Definition:
    • name: postgres:14-alpine:
      • This is the most crucial part. It specifies the Docker image to be used for the service. Here, postgres:14-alpine will pull the official PostgreSQL version 14 image (Alpine variant, which is smaller).
      • By default, the hostname your job will use to connect to this service will be derived from the image name (e.g., postgres).
    • alias: db-server:
      • (Optional) This provides an additional hostname (an alias) that your job can use to connect to this service. So, your job can reach this PostgreSQL instance via postgres (default) or db-server (alias). This is useful if you want a more generic name or if the image name contains characters not suitable for a hostname.
    • command: ["postgres", "-c", "fsync=off", ...]:
      • (Optional) You can override the default command or entrypoint of the service’s Docker image. Here, we’re passing some flags to PostgreSQL to potentially speed up its startup in a CI environment by disabling durability features not critical for CI tests. These specific flags are for CI optimization and should not be used in production.
    • variables: (under the service definition):
      • These are environment variables passed specifically to the service container (postgres:14-alpine in this case) when it starts.
      • POSTGRES_USER: $DB_USER, POSTGRES_PASSWORD: $DB_PASSWORD, POSTGRES_DB: $DB_NAME: These are standard environment variables that the postgres Docker image uses to initialize the database with a specific user, password, and database name. We are conveniently using the job-level variables (defined under integration_test_with_db.variables) to set these.
      • POSTGRES_HOST_AUTH_METHOD: "trust": This tells PostgreSQL to allow connections without password authentication from any host it can reach (which includes the job container on the same Docker network). This simplifies connections in CI but is highly insecure for production.
  3. Job-Level variables: (within integration_test_with_db):
    • DB_USER, DB_PASSWORD, DB_NAME, DB_HOST: These are defined for the main job container. The job’s script uses these to know how to connect to the database service. DB_HOST is set to postgres, which is the default hostname for the service based on its image name.
  4. before_script: (within integration_test_with_db):
    • The main job image is alpine:latest, which doesn’t have the psql (PostgreSQL client) command-line tool.
    • apk update && apk add --no-cache postgresql14-client: This installs the psql client inside the job’s container so it can interact with the PostgreSQL service.
  5. script: (within integration_test_with_db):
    • sleep 15: GitLab CI attempts to ensure services are ready before the job script starts, but complex services like databases might need a few extra seconds to initialize fully after the container is up and networking is established. This explicit sleep can help prevent connection issues. More robust solutions involve retry loops for connections.
    • PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST ...: This is how the psql client connects to the PostgreSQL service.
      • -h $DB_HOST: Specifies the hostname of the database server. This will resolve to the IP address of the postgres service container. We could also use -h db-server because of the alias.
      • -U $DB_USER: Specifies the database user.
      • -d $DB_NAME: Specifies the database name.
      • PGPASSWORD=$DB_PASSWORD: Sets the password via an environment variable for psql to avoid interactive prompts.

How It Works and Key Concepts:

  • Network Linking: GitLab creates a Docker network for the job. The main job container and all its service containers are attached to this same network. This allows them to communicate with each other using their container names (or aliases) as hostnames.
  • Service Lifecycle: Service containers are started before the before_script of your job runs and are stopped after the after_script of your job completes.
  • Hostname Resolution:
    • By default, a service is reachable via a hostname derived from its image name (e.g., postgres:14-alpine becomes postgres).
    • If an alias is provided, that alias can also be used as a hostname.
  • Common Use Cases:
    • Databases: postgres, mysql, mariadb, mongo for integration testing.
    • Caching: redis, memcached.
    • Message Queues: rabbitmq, kafka (though Kafka might be more complex for a simple service).
    • Web Servers/APIs: Running a backend API service that your frontend tests need to interact with.
    • Selenium/Browser Testing: Services like selenium/standalone-chrome.

Using services is essential for running integration tests or any job that relies on external network-accessible dependencies, allowing you to create a more realistic and self-contained testing environment within your CI pipeline.

Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x