Skip to content

Using Service containers

Service containers make it easy to work with various databases, caching services, message broker, etc. within your pipeline. For example, you might need to run integration tests that need a database or cache service.

These are essentially docker containers which are created and connected when a task/job within a workflow starts and destroyed when it completes. Your steps in a task can communicate to these using host network (localhost:<port> or 127.0.0.1:<port>).

An example -

  • For Linux VM build environment, you can use containers property to define the service containers.
  • For Docker build envionment, you can append in containers property after first element.
tasks:
  execute-tests:
    runner:
      containers:
      - image: razorci/ruby:3.3
      - image: postgres ## db service
        environment:
        - POSTGRES_DB=test
      - image: redis ## cache service
    steps:
    - checkout
    - commands:
      # Wait for the containers to be healthly using dockerize CLI
      # dockerize: https://github.com/jwilder/dockerize
      - dockerize -wait tcp://localhost:5432 -wait tcp://localhost:6379
    - run: bundle exec rspec
    ...
tasks:
  execute-tests:
    runner:
      os_image: ubuntu
      containers:
      - image: redis # cache service
      - image: postgres # db service
        environment:
        - POSTGRES_DB=test
    steps:
    - checkout
    - commands:
      # Wait for the containers to be healthly using dockerize CLI
      # dockerize: https://github.com/jwilder/dockerize
      - dockerize -wait tcp://localhost:5432 -wait tcp://localhost:6379

    - run: bundle exec rspec
    ...

Note

You can configure different service containers for each task in a workflow using runner property within the tasks.<task_id> or global. For more details, refer to "Pipeline YAML".

It uses the host network mode for the service containers. For example, if a container which binds to port 8080, the container's service will be available on port 8080 on runner VM. All ports are exposed from the container to the host VM by default.

Examples

This sections shows examples of creating service containers for various database, caching and message-broker, etc. use-cases.

Postgresql

The following example uses postgres image from Dockerhub and the service would be available at localhost:5432.

  build: # task name
    runner:
      containers:
      ...
      - image: postgres
        environment:
        - POSTGRES_DB=db_test
        - POSTGRES_USER=test
        - POSTGRES_PASSWORD=secret
        options:
        - --health-cmd pg_isready
        - --health-interval 10s
        - --health-timeout 5s
        - --health-retries 5
    steps:
    ...

    # wait for the container to be ready
    - run: dockerize -wait tcp://localhost:5432

    # connection URI: postgres://test:secret@localhost/db_test

MySQL

The following example uses mysql image from Dockerhub and the service would be available at localhost:3306. For more options, please refer to official page.

  build: # task name
    runner:
      containers:
      ...
      - image: mysql
        environment:
        - MYSQL_ROOT_PASSWORD=secret
        - MYSQL_DATABASE=db_test
        - MYSQL_ROOT_HOST=%
    steps:
    ...

    # wait for the container to be ready
    - run: dockerize -wait tcp://localhost:3306

    # connection URI: mysql://root:secret@localhost/db_test

Redis

The following example uses redis image from Dockerhub and the service would be available at localhost:6379. For more options, please refer to official page.

  build: # task name
    runner:
      containers:
      ...
      - image: redis
        options:
        - --health-cmd "redis-cli ping"
        - --health-interval 10s
        - --health-timeout 5s
        - --health-retries 5
    steps:
    ...

    # wait for the container to be ready
    - run: dockerize -wait tcp://localhost:6379

    # connection URI: redis://localhost/