.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.