Skip to content

.gitlab-ci.yml -- support for "services" port mapping, name aliasing - like docker-compose.yml

Problem to solve

Need CI support for multiple named services using same image file and different port mappings. Docker-compose and Docker-swarm support this feature.

Currently https://gitlab.com/ci/lint:

use-case:
  services:
    - postgres:latest
    - caching:
      image: redis:alpine
      ports:
        - "6380:6379"
    - queuing:
      image: redis:alpine
      ports:
        - "6381:6379"

yields

Status: syntax is incorrect 
Error: jobs:setup-test-env:services config should be an array of strings

an array of strings does not allow for port mapping, image naming, and other features found in docker-compose and docker-swarm.

From an OO design perspective, currently - service "is a" image_name_string -- direction would be to have service "has a" image_name_string and service has a many other things, such as labels [groups, masters, peers], aliases, port mappings,

Workarounds

Docker & Kubernetes

The only solution that works for both Docker and Kubernetes is either extending the image, or, if the image supports it, to use a variable to override the default port used for the service.

Service variables are a relatively new feature, and when this issue was first created, didn't exist.

For postgres, the following should work:

services:
  - name: postgres:latest
    variables:
      PGPORT: "5432"
  - name: postgres:latest
    variables:
      PGPORT: "5433"

Docker

For Docker, the existing solution is to use an alias for your service. With Docker, each service gets its own IP address. The alias configures a hostname, so you can dial each service individually using my-alias-1 and my-alias-2 etc. We have this documented, but what isn't made clear is that this only works with Docker.

We could additionally support port mapping and we could perhaps use the recently proposed runner_opts field (gitlab#385620 (closed)) for this, as this would be executor specific configuration. Having said that, I'm not sure what port mapping would provide us over using aliases. Aliases would seem to be the preferred solution for this.

Kubernetes executor:

For Kubernetes, as far as I'm aware, using aliases or port mapping to solve this won't work due to the design of the Kubernetes executor.

CI Services don't translate to Kubernetes' services, and the job, helper and service containers are all placed within the same Pod. Containers within a single pod cannot be configured with port mapping. Kubernetes has no mechanism to support this. Any containers that listen on the same port, no matter the alias, will be in conflict with one another.

Today, this means that the only workaround for Kubernetes is to extend the image/use service variables (as above).

If we wanted to support port mapping, I think we'd have to use Kubernetes services, which would likely be a significant change with security and performance implications.

Edited by Darren Eastman