2018-05-09 12:01:36 +05:30
# Building Docker images with GitLab CI/CD
2015-09-25 12:07:36 +05:30
2018-05-09 12:01:36 +05:30
GitLab CI/CD allows you to use Docker Engine to build and test docker-based projects.
2015-09-25 12:07:36 +05:30
2018-05-09 12:01:36 +05:30
TIP: **Tip:**
This also allows to you to use `docker-compose` and other docker-enabled tools.
2015-09-25 12:07:36 +05:30
2016-06-16 23:09:34 +05:30
One of the new trends in Continuous Integration/Deployment is to:
2015-09-25 12:07:36 +05:30
2018-05-09 12:01:36 +05:30
1. Create an application image
1. Run tests against the created image
1. Push image to a remote registry
1. Deploy to a server from the pushed image
2015-09-25 12:07:36 +05:30
2018-05-09 12:01:36 +05:30
It's also useful when your application already has the `Dockerfile` that can be
used to create and test an image:
2017-08-17 22:00:37 +05:30
2015-09-25 12:07:36 +05:30
```bash
2018-05-09 12:01:36 +05:30
docker build -t my-image dockerfiles/
2019-05-30 16:15:17 +05:30
docker run my-docker-image /script/to/run/tests
2018-05-09 12:01:36 +05:30
docker tag my-image my-registry:5000/my-image
docker push my-registry:5000/my-image
2015-09-25 12:07:36 +05:30
```
2018-05-09 12:01:36 +05:30
This requires special configuration of GitLab Runner to enable `docker` support
during jobs.
2015-09-25 12:07:36 +05:30
2016-06-16 23:09:34 +05:30
## Runner Configuration
2015-09-25 12:07:36 +05:30
2017-08-17 22:00:37 +05:30
There are three methods to enable the use of `docker build` and `docker run` during jobs; each with their own tradeoffs.
2016-06-16 23:09:34 +05:30
### Use shell executor
2015-09-25 12:07:36 +05:30
The simplest approach is to install GitLab Runner in `shell` execution mode.
2017-08-17 22:00:37 +05:30
GitLab Runner then executes job scripts as the `gitlab-runner` user.
2015-09-25 12:07:36 +05:30
2018-03-17 18:26:18 +05:30
1. Install [GitLab Runner ](https://gitlab.com/gitlab-org/gitlab-runner/#installation ).
2015-09-25 12:07:36 +05:30
2017-08-17 22:00:37 +05:30
1. During GitLab Runner installation select `shell` as method of executing job scripts or use command:
2015-09-25 12:07:36 +05:30
```bash
2018-03-17 18:26:18 +05:30
sudo gitlab-runner register -n \
2017-09-10 17:25:29 +05:30
--url https://gitlab.com/ \
2016-06-16 23:09:34 +05:30
--registration-token REGISTRATION_TOKEN \
2016-09-13 17:45:13 +05:30
--executor shell \
2015-09-25 12:07:36 +05:30
--description "My Runner"
```
2019-02-15 15:39:39 +05:30
1. Install Docker Engine on server.
2015-09-25 12:07:36 +05:30
2017-08-17 22:00:37 +05:30
For more information how to install Docker Engine on different systems
checkout the [Supported installations ](https://docs.docker.com/engine/installation/ ).
2015-09-25 12:07:36 +05:30
2019-02-15 15:39:39 +05:30
1. Add `gitlab-runner` user to `docker` group:
2016-06-02 11:05:42 +05:30
2015-09-25 12:07:36 +05:30
```bash
2017-08-17 22:00:37 +05:30
sudo usermod -aG docker gitlab-runner
2015-09-25 12:07:36 +05:30
```
2019-02-15 15:39:39 +05:30
1. Verify that `gitlab-runner` has access to Docker:
2016-06-02 11:05:42 +05:30
2015-09-25 12:07:36 +05:30
```bash
2017-08-17 22:00:37 +05:30
sudo -u gitlab-runner -H docker info
2015-09-25 12:07:36 +05:30
```
2016-06-02 11:05:42 +05:30
2015-09-25 12:07:36 +05:30
You can now verify that everything works by adding `docker info` to `.gitlab-ci.yml` :
2017-08-17 22:00:37 +05:30
2015-09-25 12:07:36 +05:30
```yaml
before_script:
- docker info
2016-06-02 11:05:42 +05:30
2015-09-25 12:07:36 +05:30
build_image:
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
```
2019-02-15 15:39:39 +05:30
1. You can now use `docker` command and install `docker-compose` if needed.
2015-09-25 12:07:36 +05:30
2018-05-09 12:01:36 +05:30
NOTE: **Note:**
By adding `gitlab-runner` to the `docker` group you are effectively granting `gitlab-runner` full root permissions.
2016-06-16 23:09:34 +05:30
For more information please read [On Docker security: `docker` group considered harmful ](https://www.andreas-jung.com/contents/on-docker-security-docker-group-considered-harmful ).
2015-09-25 12:07:36 +05:30
2016-06-16 23:09:34 +05:30
### Use docker-in-docker executor
2015-09-25 12:07:36 +05:30
2016-06-16 23:09:34 +05:30
The second approach is to use the special docker-in-docker (dind)
[Docker image ](https://hub.docker.com/_/docker/ ) with all tools installed
2017-08-17 22:00:37 +05:30
(`docker` and `docker-compose` ) and run the job script in context of that
2016-06-02 11:05:42 +05:30
image in privileged mode.
2016-06-16 23:09:34 +05:30
In order to do that, follow the steps:
2015-09-25 12:07:36 +05:30
2017-08-17 22:00:37 +05:30
1. Install [GitLab Runner ](https://docs.gitlab.com/runner/install ).
2015-09-25 12:07:36 +05:30
2016-06-02 11:05:42 +05:30
1. Register GitLab Runner from the command line to use `docker` and `privileged`
mode:
2015-09-25 12:07:36 +05:30
```bash
2018-03-17 18:26:18 +05:30
sudo gitlab-runner register -n \
2017-09-10 17:25:29 +05:30
--url https://gitlab.com/ \
2016-06-16 23:09:34 +05:30
--registration-token REGISTRATION_TOKEN \
2015-09-25 12:07:36 +05:30
--executor docker \
--description "My Docker Runner" \
2018-10-15 14:42:47 +05:30
--docker-image "docker:stable" \
2015-09-25 12:07:36 +05:30
--docker-privileged
```
2016-06-02 11:05:42 +05:30
The above command will register a new Runner to use the special
2018-10-15 14:42:47 +05:30
`docker:stable` image which is provided by Docker. **Notice that it's using
2016-06-02 11:05:42 +05:30
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.
The above command will create a `config.toml` entry similar to this:
```
[[runners]]
2017-09-10 17:25:29 +05:30
url = "https://gitlab.com/"
2016-06-02 11:05:42 +05:30
token = TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
2018-10-15 14:42:47 +05:30
image = "docker:stable"
2016-06-02 11:05:42 +05:30
privileged = true
disable_cache = false
volumes = ["/cache"]
[runners.cache]
Insecure = false
```
2017-08-17 22:00:37 +05:30
1. You can now use `docker` in the build script (note the inclusion of the
`docker:dind` service):
2016-06-02 11:05:42 +05:30
2015-09-25 12:07:36 +05:30
```yaml
2018-10-15 14:42:47 +05:30
image: docker:stable
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
variables:
2018-11-08 19:23:39 +05:30
# When using dind service we need to instruct docker, to talk with the
# daemon started inside of the service. The daemon is available with
# a network connection instead of the default /var/run/docker.sock socket.
#
# The 'docker' hostname is the alias of the service container as described at
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
#
# Note that if you're using Kubernetes executor, the variable should be set to
# tcp://localhost:2375 because of how Kubernetes executor connects services
# to the job container
DOCKER_HOST: tcp://docker:2375/
# When using dind, it's wise to use the overlayfs driver for
# improved performance.
2018-03-17 18:26:18 +05:30
DOCKER_DRIVER: overlay2
2017-08-17 22:00:37 +05:30
2016-06-02 11:05:42 +05:30
services:
2018-12-05 23:21:45 +05:30
- docker:dind
2016-06-02 11:05:42 +05:30
2015-09-25 12:07:36 +05:30
before_script:
2018-12-05 23:21:45 +05:30
- docker info
2016-06-02 11:05:42 +05:30
build:
stage: build
2015-09-25 12:07:36 +05:30
script:
2018-12-05 23:21:45 +05:30
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
2015-09-25 12:07:36 +05:30
```
2017-08-17 22:00:37 +05:30
Docker-in-Docker works well, and is the recommended configuration, but it is
not without its own challenges:
- By enabling `--docker-privileged` , you are effectively disabling all of
the security mechanisms of containers and exposing your host to privilege
escalation which can lead to container breakout. For more information, check
out the official Docker documentation on
[Runtime privilege and Linux capabilities][docker-cap].
- When using docker-in-docker, each job is in a clean environment without the past
history. Concurrent jobs work fine because every build gets it's own
instance of Docker engine so they won't conflict with each other. But this
also means jobs can be slower because there's no caching of layers.
- By default, `docker:dind` uses `--storage-driver vfs` which is the slowest
form offered. To use a different driver, see
[Using the overlayfs driver ](#using-the-overlayfs-driver ).
2018-03-17 18:26:18 +05:30
- Since the `docker:dind` container and the runner container don't share their
root filesystem, the job's working directory can be used as a mount point for
children containers. For example, if you have files you want to share with a
child container, you may create a subdirectory under `/builds/$CI_PROJECT_PATH`
and use it as your mount point (for a more thorough explanation, check [issue
#41227 ](https://gitlab.com/gitlab-org/gitlab-ce/issues/41227)):
```yaml
variables:
MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt
script:
- mkdir -p "$MOUNT_POINT"
- docker run -v "$MOUNT_POINT:/mnt" my-docker-image
```
2016-06-02 11:05:42 +05:30
2019-03-02 22:35:43 +05:30
An example project using this approach can be found here: < https: / / gitlab . com / gitlab-examples / docker > .
2016-06-02 11:05:42 +05:30
2016-06-16 23:09:34 +05:30
### Use Docker socket binding
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:
2017-08-17 22:00:37 +05:30
1. Install [GitLab Runner ](https://docs.gitlab.com/runner/install ).
2016-06-16 23:09:34 +05:30
1. Register GitLab Runner from the command line to use `docker` and share `/var/run/docker.sock` :
```bash
2018-03-17 18:26:18 +05:30
sudo gitlab-runner register -n \
2017-09-10 17:25:29 +05:30
--url https://gitlab.com/ \
2016-06-16 23:09:34 +05:30
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
2018-10-15 14:42:47 +05:30
--docker-image "docker:stable" \
2016-06-16 23:09:34 +05:30
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
```
The above command will register a new Runner to use the special
2018-10-15 14:42:47 +05:30
`docker:stable` image which is provided by Docker. **Notice that it's using
2017-08-17 22:00:37 +05:30
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.
2016-06-16 23:09:34 +05:30
The above command will create a `config.toml` entry similar to this:
```
[[runners]]
2017-09-10 17:25:29 +05:30
url = "https://gitlab.com/"
2016-06-16 23:09:34 +05:30
token = REGISTRATION_TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
2018-10-15 14:42:47 +05:30
image = "docker:stable"
2016-06-16 23:09:34 +05:30
privileged = false
disable_cache = false
2017-08-17 22:00:37 +05:30
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
2016-06-16 23:09:34 +05:30
[runners.cache]
Insecure = false
```
2017-08-17 22:00:37 +05:30
1. You can now use `docker` in the build script (note that you don't need to
include the `docker:dind` service as when using the Docker in Docker executor):
2016-06-16 23:09:34 +05:30
```yaml
2018-10-15 14:42:47 +05:30
image: docker:stable
2016-06-16 23:09:34 +05:30
before_script:
2018-12-05 23:21:45 +05:30
- docker info
2016-06-16 23:09:34 +05:30
build:
stage: build
script:
2018-12-05 23:21:45 +05:30
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
2016-06-16 23:09:34 +05:30
```
2017-08-17 22:00:37 +05:30
While the above method avoids using Docker in privileged mode, you should be
aware of the following implications:
2016-06-16 23:09:34 +05:30
2017-08-17 22:00:37 +05:30
- 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. For example, if a project
ran `docker rm -f $(docker ps -a -q)` it would remove the GitLab Runner
containers.
- Concurrent jobs may not work; if your tests
create containers with specific names, they may conflict with each other.
- Sharing files and directories from the source repo into containers may not
work as expected since volume mounting is done in the context of the host
machine, not the build container, e.g.:
2016-06-16 23:09:34 +05:30
2017-08-17 22:00:37 +05:30
```
docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
```
2018-05-09 12:01:36 +05:30
## Making docker-in-docker builds faster with Docker layer caching
When using docker-in-docker, Docker will download all layers of your image every
time you create a build. Recent versions of Docker (Docker 1.13 and above) can
use a pre-existing image as a cache during the `docker build` step, considerably
speeding up the build process.
### How Docker caching works
When running `docker build` , each command in `Dockerfile` results in a layer.
These layers are kept around as a cache and can be reused if there haven't been
any changes. Change in one layer causes all subsequent layers to be recreated.
You can specify a tagged image to be used as a cache source for the `docker build`
command by using the `--cache-from` argument. Multiple images can be specified
as a cache source by using multiple `--cache-from` arguments. Keep in mind that
any image that's used with the `--cache-from` argument must first be pulled
(using `docker pull` ) before it can be used as a cache source.
### Using Docker caching
Here's a simple `.gitlab-ci.yml` file showing how Docker caching can be utilized:
```yaml
2018-10-15 14:42:47 +05:30
image: docker:stable
2018-05-09 12:01:36 +05:30
services:
- docker:dind
variables:
CONTAINER_IMAGE: registry.gitlab.com/$CI_PROJECT_PATH
2018-11-08 19:23:39 +05:30
DOCKER_HOST: tcp://docker:2375
2018-05-09 12:01:36 +05:30
DOCKER_DRIVER: overlay2
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
build:
stage: build
script:
- docker pull $CONTAINER_IMAGE:latest || true
2018-12-05 23:21:45 +05:30
- docker build --cache-from $CONTAINER_IMAGE:latest --tag $CONTAINER_IMAGE:$CI_COMMIT_SHA --tag $CONTAINER_IMAGE:latest .
- docker push $CONTAINER_IMAGE:$CI_COMMIT_SHA
2018-05-09 12:01:36 +05:30
- docker push $CONTAINER_IMAGE:latest
```
The steps in the `script` section for the `build` stage can be summed up to:
1. The first command tries to pull the image from the registry so that it can be
used as a cache for the `docker build` command.
1. The second command builds a Docker image using the pulled image as a
cache (notice the `--cache-from $CONTAINER_IMAGE:latest` argument) if
available, and tags it.
1. The last two commands push the tagged Docker images to the container registry
so that they may also be used as cache for subsequent builds.
2017-08-17 22:00:37 +05:30
## Using the OverlayFS driver
2018-05-09 12:01:36 +05:30
NOTE: **Note:**
The shared Runners on GitLab.com use the `overlay2` driver by default.
2017-08-17 22:00:37 +05:30
By default, when using `docker:dind` , Docker uses the `vfs` storage driver which
copies the filesystem on every run. This is a very disk-intensive operation
2018-03-17 18:26:18 +05:30
which can be avoided if a different driver is used, for example `overlay2` .
### Requirements
2016-06-16 23:09:34 +05:30
2017-08-17 22:00:37 +05:30
1. Make sure a recent kernel is used, preferably `>= 4.2` .
1. Check whether the `overlay` module is loaded:
```
sudo lsmod | grep overlay
```
If you see no result, then it isn't loaded. To load it use:
```
sudo modprobe overlay
```
If everything went fine, you need to make sure module is loaded on reboot.
On Ubuntu systems, this is done by editing `/etc/modules` . Just add the
following line into it:
```
overlay
```
2016-06-16 23:09:34 +05:30
2018-03-17 18:26:18 +05:30
### Use driver per project
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
You can enable the driver for each project individually by editing the project's `.gitlab-ci.yml` :
```
variables:
DOCKER_DRIVER: overlay2
```
### Use driver for every project
To enable the driver for every project, you can set the environment variable for every build by adding `environment` in the `[[runners]]` section of `config.toml` :
```toml
environment = ["DOCKER_DRIVER=overlay2"]
```
If you're running multiple Runners you will have to modify all configuration files.
> **Notes:**
2018-11-20 20:47:30 +05:30
>
> - More information about the Runner configuration is available in the [Runner documentation](https://docs.gitlab.com/runner/configuration/).
> - For more information about using OverlayFS with Docker, you can read
> [Use the OverlayFS storage driver](https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/).
2017-08-17 22:00:37 +05:30
## Using the GitLab Container Registry
> **Notes:**
2018-11-20 20:47:30 +05:30
> - This feature requires GitLab 8.8 and GitLab Runner 1.2.
> - Starting from GitLab 8.12, if you have [2FA] enabled in your account, you need
> to pass a [personal access token][pat] instead of your password in order to
> login to GitLab's Container Registry.
2017-08-17 22:00:37 +05:30
Once you've built a Docker image, you can push it up to the built-in
2018-12-13 13:39:08 +05:30
[GitLab Container Registry ](../../user/project/container_registry.md ).
Some things you should be aware of:
- You must [log in to the container registry ](#authenticating-to-the-container-registry )
before running commands. You can do this in the `before_script` if multiple
jobs depend on it.
- Using `docker build --pull` fetches any changes to base
images before building just in case your cache is stale. It takes slightly
longer, but means you don’ t get stuck without security patches to base images.
- Doing an explicit `docker pull` before each `docker run` fetches
the latest image that was just built. This is especially important if you are
using multiple runners that cache images locally. Using the git SHA in your
image tag makes this less necessary since each job will be unique and you
shouldn't ever have a stale image. However, it's still possible to have a
stale image if you re-build a given commit after a dependency has changed.
- You don't want to build directly to `latest` tag in case there are multiple jobs
happening simultaneously.
### Authenticating to the Container Registry
There are three ways to authenticate to the Container Registry via GitLab CI/CD
and depend on the visibility of your project.
For all projects, mostly suitable for public ones:
- **Using the special `gitlab-ci-token` user**: This user is created for you in order to
push to the Registry connected to your project. Its password is automatically
set with the `$CI_JOB_TOKEN` variable. This allows you to automate building and deploying
your Docker images and has read/write access to the Registry. This is ephemeral,
so it's only valid for one job. You can use the following example as-is:
```sh
docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
```
For private and internal projects:
- **Using a personal access token**: You can create and use a
[personal access token ](../../user/profile/personal_access_tokens.md )
in case your project is private:
- For read (pull) access, the scope should be `read_registry` .
- For read/write (pull/push) access, use `api` .
Replace the `<username>` and `<access_token>` in the following example:
```sh
docker login -u < username > -p < access_token > $CI_REGISTRY
```
- **Using the GitLab Deploy Token**: You can create and use a
[special deploy token ](../../user/project/deploy_tokens/index.md#gitlab-deploy-token )
with your private projects. It provides read-only (pull) access to the Registry.
Once created, you can use the special environment variables, and GitLab CI/CD
will fill them in for you. You can use the following example as-is:
```sh
docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
```
### Container Registry examples
If you're using docker-in-docker on your Runners, this is how your `.gitlab-ci.yml`
2017-08-17 22:00:37 +05:30
could look like:
2016-06-16 23:09:34 +05:30
```yaml
build:
2018-10-15 14:42:47 +05:30
image: docker:stable
2016-06-16 23:09:34 +05:30
services:
2018-12-05 23:21:45 +05:30
- docker:dind
2018-11-08 19:23:39 +05:30
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
2016-06-16 23:09:34 +05:30
stage: build
script:
2017-08-17 22:00:37 +05:30
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.example.com
- docker build -t registry.example.com/group/project/image:latest .
- docker push registry.example.com/group/project/image:latest
```
You can also make use of [other variables ](../variables/README.md ) to avoid hardcoding:
```yaml
services:
- docker:dind
variables:
2018-11-08 19:23:39 +05:30
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
2018-11-18 11:00:15 +05:30
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
2017-08-17 22:00:37 +05:30
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
build:
stage: build
script:
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
2016-06-16 23:09:34 +05:30
```
2017-08-17 22:00:37 +05:30
Here, `$CI_REGISTRY_IMAGE` would be resolved to the address of the registry tied
2018-11-18 11:00:15 +05:30
to this project. Since `$CI_COMMIT_REF_NAME` resolves to the branch or tag name,
and your branch-name can contain forward slashes (e.g., feature/my-feature), it is
safer to use `$CI_COMMIT_REF_SLUG` as the image tag. This is due to that image tags
cannot contain forward slashes. We also declare our own variable, `$IMAGE_TAG` ,
2017-08-17 22:00:37 +05:30
combining the two to save us some typing in the `script` section.
2016-06-16 23:09:34 +05:30
Here's a more elaborate example that splits up the tasks into 4 pipeline stages,
2017-08-17 22:00:37 +05:30
including two tests that run in parallel. The `build` is stored in the container
2016-06-16 23:09:34 +05:30
registry and used by subsequent stages, downloading the image
when needed. Changes to `master` also get tagged as `latest` and deployed using
an application-specific deploy script:
```yaml
2018-10-15 14:42:47 +05:30
image: docker:stable
2016-06-16 23:09:34 +05:30
services:
2018-12-05 23:21:45 +05:30
- docker:dind
2016-06-16 23:09:34 +05:30
stages:
2018-12-05 23:21:45 +05:30
- build
- test
- release
- deploy
2016-06-16 23:09:34 +05:30
variables:
2018-11-08 19:23:39 +05:30
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
2019-03-02 22:35:43 +05:30
CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest
2016-06-16 23:09:34 +05:30
before_script:
2019-03-02 22:35:43 +05:30
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
2016-06-16 23:09:34 +05:30
build:
stage: build
script:
- docker build --pull -t $CONTAINER_TEST_IMAGE .
- docker push $CONTAINER_TEST_IMAGE
test1:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/tests
test2:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test
release-image:
stage: release
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
- docker push $CONTAINER_RELEASE_IMAGE
only:
- master
deploy:
stage: deploy
script:
- ./deploy.sh
only:
- master
```
2016-06-02 11:05:42 +05:30
[docker-in-docker]: https://blog.docker.com/2013/09/docker-can-now-run-within-docker/
[docker-cap]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
2017-09-10 17:25:29 +05:30
[2fa]: ../../user/profile/account/two_factor_authentication.md
[pat]: ../../user/profile/personal_access_tokens.md