Connect to a service in CI/CD
Purpose of this guide
This guide is meant to explain the different ways you might connect with services in Workshop's CI/CD, with particular regard to the ways Workshop may differ from GitLab.com.
- CI/CD troubleshooting reference: quick fixes for common connection issues.
- Differences from GitLab.com: reference for a broader comparison of GitLab.com and Workshop configuration.
Services explained
If you're coming from another CI/CD platform, you may be used to running what we call "services" (e.g., a database) through something like Docker, Docker Compose, and perhaps Docker in Docker (DinD). GitLab supports a similar approach with service images, though services are defined in addition to, rather than alongside, your main job image. Workshop does not currently support Docker in Docker.
Further information on services can be found in GitLab documentation for:
- Service section of GitLab's CI/CD YAML syntax reference: a base reference for the service syntax expected in
.gitlab-ci.ymlfiles. - GitLab's CI/CD job services guide: walks through defining services more broadly, including common tasks, pitfalls and examples for popular databases.
Defining the service
The service key defines a list of maps for each service, each usually given keys for at least:
- name: what image the service will use, e.g.,
postgres:15 - alias: token by which the service will be referenced (can be omitted if not referencing the service)
The following demonstrates how you might connect to a PostgreSQL database running as a service alongisde a test job.
Note in particular how, on line #6, the service is given an arbitrary alias of my_psql_db. That alias is then prefixed with $WSR_SERVICE_HOST_ to reference the service's host name on line #10; an important difference from GitLab.com.
run-test-suite:
stage: test
# use the postgres image as a worker so we have `psql` installed
image: postgres:15
services:
- name: postgres:15
alias: my_psql_db
variables:
POSTGRES_DB: some_db
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_URI: postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$WSR_SERVICE_HOST_my_psql_db:5432/$POSTGRES_DB
script:
- sleep 10
- psql "$POSTGRES_URI" --list
Using service references
Unlike GitLab.com, which uses an isolated virtual network, Workshop sets unpredictable hostnames for service containers that are meant to prevent collisions within a shared namespace. This means you cannot know your service's hostname in advance — to overcome this limitation we provide dynamically defined environment variables as described in the table below. These variables refer to ephemeral CloudFoundry apps, each a container deployed with the service image.
| Variable prefix | Usage example | Description |
|---|---|---|
WSR_SERVICE_ID_ | $WSR_SERVICE_ID_my_alias | CloudFoundry app ID |
WSR_SERVICE_HOST_ | $WSR_SERVICE_HOST_my_alias | CloudFoundry app hostname |
Using refs in…
✅ [job].variables
Your jobs’ variables blocks are probably the most common place you'll use service references.
run-test-suite:
stage: test
services:
- name: postgres:15
alias: my_psql_db
variables:
POSTGRES_DB: some_db
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_URI: postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$WSR_SERVICE_HOST_my_psql_db:5432/$POSTGRES_DB
script:
- psql "$POSTGRES_URI"
✅ [job].script
You can also reference services directly from script steps.
run-test-suite:
stage: test
services:
- name: postgres:15
alias: my_psql_db
variables:
POSTGRES_DB: some_db
POSTGRES_USER: user
POSTGRES_PASSWORD: password
script:
- psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$WSR_SERVICE_HOST_my_psql_db:5432/$POSTGRES_DB"
✅ [job].before_script
In some circumstances you may want to use service references in a before_script. Here’s an example where we dynamically define a variable on all jobs by adding it to the default.before_script.
default:
services:
- name: postgres:15
alias: my_psql_db
before_script:
- export DB_URI="postgresql://$DYN_USER:$DYN_PASS@$WSR_SERVICE_HOST_my_psql_db:5432/$DYN_DB"
❌ [job].services.0.variables
Service references will not work within services[...].variables.
The main exception is within the services' own variables block, i.e., services[...].variables. Variables within that block are not currently interpreted due to a design decision by GitLab.
Ergo, the below configuration will not work.
run-test-suite:
stage: test
services:
- name: postgres:15
alias: my_missing_db
- name: custom_app:latest
variables:
DB_URI: "failql://$POSTGRES_USER:$POSTGRES_PASSWORD@$WSR_SERVICE_HOST_my_missing_db:5432/$POSTGRES_DB"
variables:
POSTGRES_DB: broke_db
POSTGRES_USER: user
POSTGRES_PASSWORD: password