summaryrefslogtreecommitdiff
path: root/doc/ci/services/index.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/ci/services/index.md')
-rw-r--r--doc/ci/services/index.md376
1 files changed, 368 insertions, 8 deletions
diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md
index 71c2be70de3..8d603b17e2e 100644
--- a/doc/ci/services/index.md
+++ b/doc/ci/services/index.md
@@ -6,16 +6,376 @@ comments: false
type: index
---
-# GitLab CI services examples
+# Services
-The [`services`](../docker/using_docker_images.md#what-is-a-service)
-keyword defines a Docker image that runs during a `job` linked to the
-Docker image that the image keyword defines. This allows you to access
-the service image during build time.
+The `services` keyword defines a Docker image that runs during a `job`
+linked to the Docker image that the image keyword defines. This allows
+you to access the service image during build time.
The service image can run any application, but the most common use
case is to run a database container, for example:
-- [Using MySQL](mysql.md)
-- [Using PostgreSQL](postgres.md)
-- [Using Redis](redis.md)
+- [MySQL](mysql.md)
+- [PostgreSQL](postgres.md)
+- [Redis](redis.md)
+- [GitLab](gitlab.md) as an example for a microservice offering a JSON API
+
+It's easier and faster to use an existing image and run it as an additional container
+than to install `mysql`, for example, every time the project is built.
+
+You're not limited to only database services. You can add as many
+services you need to `.gitlab-ci.yml` or manually modify `config.toml`.
+Any image found at [Docker Hub](https://hub.docker.com/) or your private Container Registry can be
+used as a service.
+
+Services inherit the same DNS servers, search domains, and additional hosts as
+the CI container itself.
+
+## How services are linked to the job
+
+To better understand how container linking works, read
+[Linking containers together](https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/).
+
+If you add `mysql` as service to your application, the image is
+used to create a container that's linked to the job container.
+
+The service container for MySQL is accessible under the hostname `mysql`.
+To access your database service, connect to the host named `mysql` instead of a
+socket or `localhost`. Read more in [accessing the services](#accessing-the-services).
+
+## How the health check of services works
+
+Services are designed to provide additional features which are **network accessible**.
+They may be a database like MySQL, or Redis, and even `docker:stable-dind` which
+allows you to use Docker-in-Docker. It can be practically anything that's
+required for the CI/CD job to proceed, and is accessed by network.
+
+To make sure this works, the runner:
+
+1. Checks which ports are exposed from the container by default.
+1. Starts a special container that waits for these ports to be accessible.
+
+If the second stage of the check fails, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`.
+This issue can occur because:
+
+- There is no opened port in the service.
+- The service was not started properly before the timeout, and the port is not
+ responding.
+
+In most cases it affects the job, but there may be situations when the job
+still succeeds even if that warning was printed. For example:
+
+- The service was started shortly after the warning was raised, and the job is
+ not using the linked service from the beginning. In that case, when the
+ job needed to access the service, it may have been already there waiting for
+ connections.
+- The service container is not providing any networking service, but it's doing
+ something with the job's directory (all services have the job directory mounted
+ as a volume under `/builds`). In that case, the service does its job, and
+ because the job is not trying to connect to it, it does not fail.
+
+## What services are not for
+
+As mentioned before, this feature is designed to provide **network accessible**
+services. A database is the simplest example of such a service.
+
+The services feature is not designed to, and does not, add any software from the
+defined `services` image(s) to the job's container.
+
+For example, if you have the following `services` defined in your job, the `php`,
+`node` or `go` commands are **not** available for your script, and the job fails:
+
+```yaml
+job:
+ services:
+ - php:7
+ - node:latest
+ - golang:1.10
+ image: alpine:3.7
+ script:
+ - php -v
+ - node -v
+ - go version
+```
+
+If you need to have `php`, `node` and `go` available for your script, you should
+either:
+
+- Choose an existing Docker image that contains all required tools.
+- Create your own Docker image, with all the required tools included,
+ and use that in your job.
+
+## Define `services` in the `.gitlab-ci.yml` file
+
+It's also possible to define different images and services per job:
+
+```yaml
+default:
+ before_script:
+ - bundle install
+
+test:2.6:
+ image: ruby:2.6
+ services:
+ - postgres:11.7
+ script:
+ - bundle exec rake spec
+
+test:2.7:
+ image: ruby:2.7
+ services:
+ - postgres:12.2
+ script:
+ - bundle exec rake spec
+```
+
+Or you can pass some [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options)
+for `image` and `services`:
+
+```yaml
+default:
+ image:
+ name: ruby:2.6
+ entrypoint: ["/bin/bash"]
+
+ services:
+ - name: my-postgres:11.7
+ alias: db-postgres
+ entrypoint: ["/usr/local/bin/db-postgres"]
+ command: ["start"]
+
+ before_script:
+ - bundle install
+
+test:
+ script:
+ - bundle exec rake spec
+```
+
+## Accessing the services
+
+Let's say that you need a Wordpress instance to test some API integration with
+your application. You can then use for example the
+[`tutum/wordpress`](https://hub.docker.com/r/tutum/wordpress/) image in your
+`.gitlab-ci.yml` file:
+
+```yaml
+services:
+ - tutum/wordpress:latest
+```
+
+If you don't [specify a service alias](#available-settings-for-services),
+when the job runs, `tutum/wordpress` is started. You have
+access to it from your build container under two hostnames:
+
+- `tutum-wordpress`
+- `tutum__wordpress`
+
+Hostnames with underscores are not RFC valid and may cause problems in third-party
+applications.
+
+The default aliases for the service's hostname are created from its image name
+following these rules:
+
+- Everything after the colon (`:`) is stripped.
+- Slash (`/`) is replaced with double underscores (`__`) and the primary alias
+ is created.
+- Slash (`/`) is replaced with a single dash (`-`) and the secondary alias is
+ created (requires GitLab Runner v1.1.0 or higher).
+
+To override the default behavior, you can
+[specify a service alias](#available-settings-for-services).
+
+## Passing CI/CD variables to services
+
+You can also pass custom CI/CD [variables](../variables/README.md)
+to fine tune your Docker `images` and `services` directly in the `.gitlab-ci.yml` file.
+For more information, read about [`.gitlab-ci.yml` defined variables](../variables/README.md#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
+
+```yaml
+# The following variables are automatically passed down to the Postgres container
+# as well as the Ruby container and available within each.
+variables:
+ HTTPS_PROXY: "https://10.1.1.1:8090"
+ HTTP_PROXY: "https://10.1.1.1:8090"
+ POSTGRES_DB: "my_custom_db"
+ POSTGRES_USER: "postgres"
+ POSTGRES_PASSWORD: "example"
+ PGDATA: "/var/lib/postgresql/data"
+ POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums"
+
+services:
+ - name: postgres:11.7
+ alias: db
+ entrypoint: ["docker-entrypoint.sh"]
+ command: ["postgres"]
+
+image:
+ name: ruby:2.6
+ entrypoint: ["/bin/bash"]
+
+before_script:
+ - bundle install
+
+test:
+ script:
+ - bundle exec rake spec
+```
+
+## Available settings for `services`
+
+> Introduced in GitLab and GitLab Runner 9.4.
+
+| Setting | Required | GitLab version | Description |
+|------------|----------|----------------| ----------- |
+| `name` | yes, when used with any other option | 9.4 | Full name of the image to use. It should contain the Registry part if needed. |
+| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
+| `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. |
+| `alias` (1) | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
+
+(1) Alias support for the Kubernetes executor was [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2229) in GitLab Runner 12.8, and is only available for Kubernetes version 1.7 or later.
+
+## Starting multiple services from the same image
+
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options).
+
+Before the new extended Docker configuration options, the following configuration
+would not work properly:
+
+```yaml
+services:
+ - mysql:latest
+ - mysql:latest
+```
+
+The runner would start two containers, each that uses the `mysql:latest` image.
+However, both of them would be added to the job's container with the `mysql` alias, based on
+the [default hostname naming](#accessing-the-services). This would end with one
+of the services not being accessible.
+
+After the new extended Docker configuration options, the above example would
+look like:
+
+```yaml
+services:
+ - name: mysql:latest
+ alias: mysql-1
+ - name: mysql:latest
+ alias: mysql-2
+```
+
+The runner still starts two containers using the `mysql:latest` image,
+however now each of them are also accessible with the alias configured
+in `.gitlab-ci.yml` file.
+
+## Setting a command for the service
+
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options).
+
+Let's assume you have a `super/sql:latest` image with some SQL database
+in it. You would like to use it as a service for your job. Let's also
+assume that this image does not start the database process while starting
+the container. The user needs to manually use `/usr/bin/super-sql run` as
+a command to start the database.
+
+Before the new extended Docker configuration options, you would need to:
+
+- Create your own image based on the `super/sql:latest` image.
+- Add the default command.
+- Use the image in the job's configuration:
+
+ ```dockerfile
+ # my-super-sql:latest image's Dockerfile
+
+ FROM super/sql:latest
+ CMD ["/usr/bin/super-sql", "run"]
+ ```
+
+ ```yaml
+ # .gitlab-ci.yml
+
+ services:
+ - my-super-sql:latest
+ ```
+
+After the new extended Docker configuration options, you can
+set a `command` in the `.gitlab-ci.yml` file instead:
+
+```yaml
+# .gitlab-ci.yml
+
+services:
+ - name: super/sql:latest
+ command: ["/usr/bin/super-sql", "run"]
+```
+
+The syntax of `command` is similar to [Dockerfile's `CMD`](https://docs.docker.com/engine/reference/builder/#cmd).
+
+## How Docker integration works
+
+Below is a high level overview of the steps performed by Docker during job
+time.
+
+1. Create any service container: `mysql`, `postgresql`, `mongodb`, `redis`.
+1. Create a cache container to store all volumes as defined in `config.toml` and
+ `Dockerfile` of build image (`ruby:2.6` as in above example).
+1. Create a build container and link any service container to build container.
+1. Start the build container, and send a job script to the container.
+1. Run the job script.
+1. Checkout code in: `/builds/group-name/project-name/`.
+1. Run any step defined in `.gitlab-ci.yml`.
+1. Check the exit status of build script.
+1. Remove the build container and all created service containers.
+
+## Debug a job locally
+
+The following commands are run without root privileges. You should be
+able to run Docker with your regular user account.
+
+First start with creating a file named `build_script`:
+
+```shell
+cat <<EOF > build_script
+git clone https://gitlab.com/gitlab-org/gitlab-runner.git /builds/gitlab-org/gitlab-runner
+cd /builds/gitlab-org/gitlab-runner
+make
+EOF
+```
+
+Here we use as an example the GitLab Runner repository which contains a
+Makefile, so running `make` executes the commands defined in the Makefile.
+Instead of `make`, you could run the command which is specific to your project.
+
+Then create some service containers:
+
+```shell
+docker run -d --name service-mysql mysql:latest
+docker run -d --name service-postgres postgres:latest
+```
+
+This creates two service containers, named `service-mysql` and
+`service-postgres` which use the latest MySQL and PostgreSQL images
+respectively. They both run in the background (`-d`).
+
+Finally, create a build container by executing the `build_script` file we
+created earlier:
+
+```shell
+docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.6 /bin/bash < build_script
+```
+
+The above command creates a container named `build` that's spawned from
+the `ruby:2.6` image and has two services linked to it. The `build_script` is
+piped using `stdin` to the bash interpreter which in turn executes the
+`build_script` in the `build` container.
+
+When you finish testing and no longer need the containers, you can remove them
+with:
+
+```shell
+docker rm -f -v build service-mysql service-postgres
+```
+
+This forcefully (`-f`) removes the `build` container, the two service
+containers, and all volumes (`-v`) that were created with the container
+creation.