2015-08-26 01:42:46 +00:00
# Using Docker Build
2015-09-26 18:15:58 +00:00
GitLab CI allows you to use Docker Engine to build and test docker-based projects.
2015-08-26 01:42:46 +00:00
**This also allows to you to use `docker-compose` and other docker-enabled tools.**
2016-06-08 04:33:54 +00:00
This is one of the new trends in Continuous Integration/Deployment to:
2015-08-26 01:42:46 +00:00
2016-06-08 04:33:54 +00:00
1. create an application image,
1. run tests against the created image,
1. push image to a remote registry,
1. deploy server from the pushed image
2015-08-26 01:42:46 +00:00
2016-06-08 04:33:54 +00:00
It's also useful when your application already has the `Dockerfile` that can be used to create and test an image:
2015-08-26 01:42:46 +00:00
```bash
$ docker build -t my-image dockerfiles/
$ docker run my-docker-image /script/to/run/tests
$ docker tag my-image my-registry:5000/my-image
$ docker push my-registry:5000/my-image
```
2016-06-08 04:33:54 +00:00
However, this requires special configuration of GitLab Runner to enable `docker` support during builds. There are three methods to enable the use of `docker build` and `docker run` during builds.
2015-08-26 01:42:46 +00:00
## 1. Use shell executor
The simplest approach is to install GitLab Runner in `shell` execution mode.
GitLab Runner then executes build scripts as `gitlab-runner` user.
1. Install [GitLab Runner ](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/#installation ).
1. During GitLab Runner installation select `shell` as method of executing build scripts or use command:
```bash
$ sudo gitlab-runner register -n \
2015-11-16 10:01:26 +00:00
--url https://gitlab.com/ci \
2015-08-26 01:42:46 +00:00
--token RUNNER_TOKEN \
--executor shell
--description "My Runner"
```
2016-05-07 05:54:36 +00:00
2. Install Docker Engine on server.
2015-08-26 01:42:46 +00:00
2016-05-07 05:54:36 +00:00
For more information how to install Docker Engine on different systems checkout the [Supported installations ](https://docs.docker.com/engine/installation/ ).
2015-08-26 01:42:46 +00:00
3. Add `gitlab-runner` user to `docker` group:
2016-04-25 11:51:17 +00:00
2015-08-26 01:42:46 +00:00
```bash
$ sudo usermod -aG docker gitlab-runner
```
4. Verify that `gitlab-runner` has access to Docker:
2016-04-25 11:51:17 +00:00
2015-08-26 01:42:46 +00:00
```bash
$ sudo -u gitlab-runner -H docker info
```
2016-04-25 11:51:17 +00:00
2015-08-26 01:42:46 +00:00
You can now verify that everything works by adding `docker info` to `.gitlab-ci.yml` :
```yaml
before_script:
- docker info
2016-04-25 11:51:17 +00:00
2015-08-26 01:42:46 +00:00
build_image:
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
```
5. You can now use `docker` command and install `docker-compose` if needed.
6. However, by adding `gitlab-runner` to `docker` group you are effectively granting `gitlab-runner` full root permissions.
For more information please checkout [On Docker security: `docker` group considered harmful ](https://www.andreas-jung.com/contents/on-docker-security-docker-group-considered-harmful ).
## 2. Use docker-in-docker executor
2016-04-28 10:04:53 +00:00
The second approach is to use the special Docker image with all tools installed
(`docker` and `docker-compose` ) and run the build script in context of that
image in privileged mode.
2015-08-26 01:42:46 +00:00
In order to do that follow the steps:
1. Install [GitLab Runner ](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/#installation ).
2016-04-28 10:04:53 +00:00
1. Register GitLab Runner from the command line to use `docker` and `privileged`
mode:
2015-08-26 01:42:46 +00:00
```bash
2016-04-28 10:04:53 +00:00
sudo gitlab-runner register -n \
2015-11-16 10:01:26 +00:00
--url https://gitlab.com/ci \
2015-08-26 01:42:46 +00:00
--token RUNNER_TOKEN \
--executor docker \
--description "My Docker Runner" \
2016-04-25 11:51:17 +00:00
--docker-image "docker:latest" \
2015-08-26 01:42:46 +00:00
--docker-privileged
```
2016-04-25 11:51:17 +00:00
2016-04-28 10:04:53 +00:00
The above command will register a new Runner to use the special
`docker:latest` image which is provided by Docker. **Notice that it's using
the `privileged` mode to start the build and service containers.** If you
want to use [docker-in-docker] mode, you always have to use `privileged = true`
in your Docker containers.
2016-04-25 11:51:17 +00:00
The above command will create a `config.toml` entry similar to this:
```
[[runners]]
url = "https://gitlab.com/ci"
token = TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:latest"
privileged = true
disable_cache = false
volumes = ["/cache"]
[runners.cache]
Insecure = false
```
2016-04-28 10:04:53 +00:00
If you want to use the Shared Runners available on your GitLab CE/EE
installation in order to build Docker images, then make sure that your
Shared Runners configuration has the `privileged` mode set to `true` .
2015-08-26 01:42:46 +00:00
1. You can now use `docker` from build script:
2016-04-25 11:51:17 +00:00
2015-08-26 01:42:46 +00:00
```yaml
2016-04-25 11:51:17 +00:00
image: docker:latest
services:
- docker:dind
2015-08-26 01:42:46 +00:00
before_script:
2016-04-28 10:04:53 +00:00
- docker info
2016-04-25 11:51:17 +00:00
build:
stage: build
2015-08-26 01:42:46 +00:00
script:
2016-04-25 11:51:17 +00:00
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
2015-08-26 01:42:46 +00:00
```
2016-04-28 10:04:53 +00:00
1. However, by enabling `--docker-privileged` you are effectively disabling all
the security mechanisms of containers and exposing your host to privilege
escalation which can lead to container breakout.
2016-04-25 11:51:17 +00:00
2016-04-28 10:04:53 +00:00
For more information, check out the official Docker documentation on
[Runtime privilege and Linux capabilities][docker-cap].
2016-04-25 11:51:17 +00:00
An example project using this approach can be found here: https://gitlab.com/gitlab-examples/docker.
2016-04-28 10:04:53 +00:00
2016-06-08 04:33:54 +00:00
## 3. Bind Docker socket
The third approach is to bind-mount `/var/run/docker.sock` into the container so that docker is available in the context of that image.
In order to do that follow the steps:
1. Install [GitLab Runner ](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/#installation ).
1. Register GitLab Runner from the command line to use `docker` and `privileged`
mode:
```bash
sudo gitlab-runner register -n \
--url https://gitlab.com/ci \
--token RUNNER_TOKEN \
--executor docker \
--description "My Docker Runner" \
--docker-image "docker:latest" \
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
```
The above command will register a new Runner to use the special
`docker:latest` image which is provided by Docker. **Notice that it's using
the Docker daemon of the runner itself, and any containers spawned by docker commands will be siblings of the runner rather than children of the runner.** This may have complications and limitations that are unsuitable for your workflow.
The above command will create a `config.toml` entry similar to this:
```
[[runners]]
url = "https://gitlab.com/ci"
token = TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:latest"
privileged = false
disable_cache = false
volumes = ["/usr/local/bin/docker:/usr/bin/docker", "/cache"]
[runners.cache]
Insecure = false
```
1. You can now use `docker` from build script (note that you don't need to include the `docker:dind` service as in the option above):
```yaml
image: docker:latest
before_script:
- docker info
build:
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
```
1. However, by sharing the docker daemon, you are effectively disabling all
the security mechanisms of containers and exposing your host to privilege
escalation which can lead to container breakout.
2016-04-28 10:04:53 +00:00
[docker-in-docker]: https://blog.docker.com/2013/09/docker-can-now-run-within-docker/
2016-05-07 05:54:36 +00:00
[docker-cap]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities