Skip to content

Use Docker volumes instead of cache containers

Steve Xuereb requested to merge 4450-use-volume-container-id into master

What does this MR do?

Use docker volume create to define volumes for the build instead of creating "cache containers"

Docker commands we used to run:

docker inspect $CACHE_CONTAINER
docker create gitlab/gitlab-runner-helper:xxxx cache-init
docker start $CACHE_CONTAINER
docker wait $CACHE_CONTAINER
docker run --volumes-from $CACHE_CONTAINER $IMAGE

Docker commands we run now:

docker volume create $VOLUME_NAME
docker run -v $VOLUME_NAME:/cache $IMAGE

Why was this MR needed?

Problem: cache containers are containers created specifically to create volumes and initialize them correctly and exit properly. Then each container that is created afterword the --volumes-from is passed specifying the container ids of the exited cache containers. As seen in #4450 (comment 316034514) the ContainerCreate can return a 404 if we define a --volumes-from to a nonexisting container. Exited containers can easily be removed/cleanup by some other system they are also susceptible to oom killer/cgroups so the resource is more temporary.

Solution: Instead of creating a cache container and then keep reusing that container to specify volume mounts. Create a volume with docker volume create and define it part of the bindings, for example $VOLUME_NAME:/cache. Using volumes directly has the following benefits:

  • gitlab.com/gitlab-org/gitlab-runner/executors/docker/internal/volumes is much simpler since we don't have to manage more containers.
  • Volumes don't randomly get removed the same way as exited cache containers do.
  • Permissions are set by default since rw is implied, so no cache-init command is needed.
  • If a volume with that name is already created it's reused, Docker doesn't return an error.
  • Achieve what we are doing in fewer steps, creating fewer containers which makes the build faster especially on Windows where we used large containers.

The volumes aren't labeled the same as the current ones that we create, for this please take a look at #25300 (closed).

Testing: !1989 (merged)

We use e.builds to keep track of how many containers we created and use the length to define predefined containers. Remove the need for this and rely on a unix timestamp to be unique.

The e.builds was used to get the volumes from a container, but now we are always using the cache contaienr ID so there is no need to store these containerIDs and waste memory, especially since the Runner doesn't have control over the containers and they can be removed at any time.

If we would require the IDs again in the future for some usecase we should add it then.

Remove the cache-init command: This command was being used to initialize the cache directory with the correct permissions. This is no longer needed since docker volume create is being used and it has rw (read-write) so the directory already has the expected permissions.

docker volume create: https://docs.docker.com/engine/reference/commandline/volume_create/

Manual Testing (already in unit tests)

Build directory is reused (Linux)

.config.toml
[[runners]]
  name = "docker"
  url = "http://192.168.144.160:3000"
  token = "ixxx"
  executor = "docker"
  environment = ["IMAGE=alpine"]
  [runners.docker]
    tls_verify = false
    image = "alpine:3.11"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
.gitlab-ci.yml
variables:
  IMAGE: alpine:3.11

job:
  variables:
    TEST: test
  image: ${IMAGE}
  script:
  - ls -la
  - echo $CI_REGISTRY_USER
  - echo $CI_JOB_TOKEN
  - echo $IMAGE
  - echo $TEST
docker volume ls before first run
$ docker volume ls
DRIVER              VOLUME NAME
first job run: Create fresh repository
Running with gitlab-runner development version (HEAD)
   on docker fL_5iHR7
Preparing the "docker" executor
 Using Docker executor with image alpine:3.11 ...
 Pulling docker image alpine:3.11 ...
 Using docker image sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72 for alpine:3.11 ...
Preparing environment
00:01
 Running on runner-fl5ihr7-project-19-concurrent-0 via steve-mbp-gitlab.local...
Getting source from Git repository
00:02
 Fetching changes with git depth set to 50...
 Initialized empty Git repository in /builds/root/playground/.git/
 Created fresh repository.
 From http://192.168.144.160:3000/root/playground
  * [new ref]         refs/pipelines/343 -> refs/pipelines/343
  * [new branch]      master             -> origin/master
 Checking out 1a5762e7 as master...
 Skipping Git submodules setup
Restoring cache
00:01
Downloading artifacts
00:01
Running before_script and script
00:02
 $ ls -la
 total 20
 drwxrwxrwx    4 root     root          4096 Apr  6 07:00 .
 drwxrwxrwx    4 root     root          4096 Apr  6 07:00 ..
 drwxrwxrwx    6 root     root          4096 Apr  6 07:00 .git
 drwxrwxrwx    2 root     root          4096 Apr  6 07:00 .gitlab
 -rw-rw-rw-    1 root     root           187 Apr  6 07:00 .gitlab-ci.yml
 $ echo $CI_REGISTRY_USER
 gitlab-ci-token
 $ echo $CI_JOB_TOKEN
 [MASKED]
 $ echo $IMAGE
 alpine:3.11
 $ echo $TEST
 test
Running after_script
00:01
Saving cache
00:01
Uploading artifacts for successful job
00:02
 Job succeeded
Second run: Reuse build directory: fetch changes instead of new repository
   on docker fL_5iHR7
Preparing the "docker" executor
 Using Docker executor with image alpine:3.11 ...
 Pulling docker image alpine:3.11 ...
 Using docker image sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72 for alpine:3.11 ...
Preparing environment
00:01
 Running on runner-fl5ihr7-project-19-concurrent-0 via steve-mbp-gitlab.local...
Getting source from Git repository
00:03
 Fetching changes with git depth set to 50...
 Reinitialized existing Git repository in /builds/root/playground/.git/
 Checking out 1a5762e7 as master...
 Skipping Git submodules setup
Restoring cache
00:01
Downloading artifacts
Running before_script and script
00:02
 $ ls -la
 total 20
 drwxrwxrwx    4 root     root          4096 Apr  6 07:00 .
 drwxrwxrwx    4 root     root          4096 Apr  6 07:00 ..
 drwxrwxrwx    6 root     root          4096 Apr  6 07:02 .git
 drwxrwxrwx    2 root     root          4096 Apr  6 07:00 .gitlab
 -rw-rw-rw-    1 root     root           187 Apr  6 07:00 .gitlab-ci.yml
 $ echo $CI_REGISTRY_USER
 gitlab-ci-token
 $ echo $CI_JOB_TOKEN
 [MASKED]
 $ echo $IMAGE
 alpine:3.11
 $ echo $TEST
 test
Running after_script
Saving cache
00:01
Uploading artifacts for successful job
00:02
 Job succeeded
docker volume ls
$ docker volume ls
DRIVER              VOLUME NAME
local               runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
local               runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8
volumes mounted to container
$ docker inspect 4fc617ee8dfe | jq .[].Mounts
[
  {
    "Type": "volume",
    "Name": "runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70",
    "Source": "/var/lib/docker/volumes/runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70/_data",
    "Destination": "/cache",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8",
    "Source": "/var/lib/docker/volumes/runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8/_data",
    "Destination": "/builds",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
  }
]

$ docker volume ls
DRIVER              VOLUME NAME
local               runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
local               runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8

Build directory is reused (Windows)

.config.toml
[[runners]]
[[runners]]
  name = "windows-docker"
  url = "http://192.168.144.160:3000"
  token = "xxx"
  executor = "docker-windows"
  [runners.docker]
    tls_verify = false
    image = "mcr.microsoft.com/windows/servercore:1809"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["c:\\cache"]
    pull_policy = "if-not-present"
    shm_size = 0
    helper_image = "gitlab/gitlab-runner-helper:x86_64-latest-servercore1809"
.gitlab-ci.yml
variables:
  IMAGE: alpine:3.11

job:
  variables:
    TEST: test
  image: ${IMAGE}
  script:
  - ls -la
  - echo $CI_REGISTRY_USER
  - echo $CI_JOB_TOKEN
  - echo $IMAGE
  - echo $TEST
docker volume ls before first run
$ docker volume ls
DRIVER              VOLUME NAME
first job run: Create fresh repository
 Running with gitlab-runner 12.10.0~beta.113.g11a29b22 (11a29b22)
   on windows-docker LnGUusC8
Preparing the "docker-windows" executor
00:00
 Using Docker executor with image mcr.microsoft.com/windows/servercore:1809 ...
 Using locally found image version due to if-not-present pull policy
 Using docker image sha256:528a5fb201d35ba08a4ae7e3ea8909e8ba961d9747f55742f2c2683231f5fc00 for gitlab/gitlab-runner-helper:x86_64-latest-servercore1809 ...
 Using locally found image version due to if-not-present pull policy
 Using docker image sha256:73d9a9b9c9fbac1c83098752ed8995af271895586abcfbf5824f559b55a1d536 for mcr.microsoft.com/windows/servercore:1809 ...
Preparing environment
 Running on RUNNER-LNGUUSC8 via
 vagrant-2019...
Getting source from Git repository
 Fetching changes with git depth set to 50...
 Initialized empty Git repository in c:/builds/root/playground/.git/
 Created fresh repository.
 From http://192.168.144.160:3000/root/playground
  * [new ref]         refs/pipelines/341 -> refs/pipelines/341
  * [new branch]      master             -> origin/master
 Checking out 1a5762e7 as master...
 git-lfs/2.7.1 (GitHub; windows amd64; go 1.11.5; git 6b7fb6e3)
 Skipping Git submodules setup
Restoring cache
Downloading artifacts
Running before_script and script
 $ ls -la
 Get-ChildItem : A parameter cannot be found that matches parameter name 'la'.
 At line:1 char:4
 + ls -la
 +    ~~~
     + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], ParameterB
    indingException
     + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm
    ands.GetChildItemCommand

Uploading artifacts for failed job
 ERROR: Job failed: exit code 1
Second run: Reuse build directory: fetch changes instead of new repository
 Running with gitlab-runner 12.10.0~beta.113.g11a29b22 (11a29b22)
   on windows-docker LnGUusC8
Preparing the "docker-windows" executor
00:00
 Using Docker executor with image mcr.microsoft.com/windows/servercore:1809 ...
 Using locally found image version due to if-not-present pull policy
 Using docker image sha256:528a5fb201d35ba08a4ae7e3ea8909e8ba961d9747f55742f2c2683231f5fc00 for gitlab/gitlab-runner-helper:x86_64-latest-servercore1809 ...
 Using locally found image version due to if-not-present pull policy
 Using docker image sha256:73d9a9b9c9fbac1c83098752ed8995af271895586abcfbf5824f559b55a1d536 for mcr.microsoft.com/windows/servercore:1809 ...
Preparing environment
 Running on RUNNER-LNGUUSC8 via
 vagrant-2019...
Getting source from Git repository
 Fetching changes with git depth set to 50...
 Reinitialized existing Git repository in c:/builds/root/playground/.git/
 Checking out 1a5762e7 as master...
 git-lfs/2.7.1 (GitHub; windows amd64; go 1.11.5; git 6b7fb6e3)
 Skipping Git submodules setup
Restoring cache
Downloading artifacts
Running before_script and script
 $ ls -la
 Get-ChildItem : A parameter cannot be found that matches parameter name 'la'.
 At line:1 char:4
 + ls -la
 +    ~~~
     + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], ParameterB
    indingException
     + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm
    ands.GetChildItemCommand

Uploading artifacts for failed job
 ERROR: Job failed: exit code 1
docker volume ls
$ docker volume ls
DRIVER              VOLUME NAME
local               runner-lnguusc8-project-19-concurrent-0-cache-256a2a0a21f7076b19809f2a24b91cbb
local               runner-lnguusc8-project-19-concurrent-0-cache-cde2929a41401004cf47d36bdb2eb380
volumes mounted to container
$ docker inspect 454953e8ba20
...
     "Mounts": [
            {
                "Type": "volume",
                "Name": "runner-lnguusc8-project-19-concurrent-0-cache-256a2a0a21f7076b19809f2a24b91cbb",
                "Source": "C:\\ProgramData\\docker\\volumes\\runner-lnguusc8-project-19-concurrent-0-cache-256a2a0a21f7076b19809f2a24b91cbb\\_data",
                "Destination": "c:\\cache",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "runner-lnguusc8-project-19-concurrent-0-cache-cde2929a41401004cf47d36bdb2eb380",
                "Source": "C:\\ProgramData\\docker\\volumes\\runner-lnguusc8-project-19-concurrent-0-cache-cde2929a41401004cf47d36bdb2eb380\\_data",
                "Destination": "c:\\builds",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...

$ docker volume ls
DRIVER              VOLUME NAME
local               runner-lnguusc8-project-19-concurrent-0-cache-256a2a0a21f7076b19809f2a24b91cbb
local               runner-lnguusc8-project-19-concurrent-0-cache-cde2929a41401004cf47d36bdb2eb380

Cache (Defined inside of volumes)

.config.toml
[[runners]]
  name = "docker"
  url = "http://192.168.144.160:3000"
  token = "ixxx"
  executor = "docker"
  environment = ["IMAGE=alpine"]
  [runners.docker]
    tls_verify = false
    image = "alpine:3.11"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
.gitlab-ci.yml
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
  - cache

job:
  stage: test
  script:
  - mkdir -p cache
  - touch cache/tada
  - echo "hello" > cache/hello.txt
  - ls -la
  - ls -la cache
job log
 Running with gitlab-runner development version (HEAD)
   on docker fL_5iHR7
Preparing the "docker" executor
00:05
 Using Docker executor with image alpine:3.11 ...
 Pulling docker image alpine:3.11 ...
 Using docker image sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72 for alpine:3.11 ...
Preparing environment
 Running on runner-fl5ihr7-project-19-concurrent-0 via steve-mbp-gitlab.local...
Getting source from Git repository
00:01
 Fetching changes with git depth set to 50...
 Reinitialized existing Git repository in /builds/root/playground/.git/
 From http://192.168.144.160:3000/root/playground
  * [new ref]         refs/pipelines/342 -> refs/pipelines/342
  * [new branch]      cache              -> origin/cache
 Checking out 373eee15 as cache...
 Skipping Git submodules setup
Restoring cache
 Checking cache for cache...
 No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
 Successfully extracted cache
Downloading artifacts
00:02
Running before_script and script
00:01
 $ mkdir -p cache
 $ touch cache/tada
 $ echo "hello" > cache/hello.txt
 $ ls -la
 total 20
 drwxrwxrwx    4 root     root          4096 Apr  6 06:38 .
 drwxrwxrwx    4 root     root          4096 Apr  6 06:18 ..
 drwxrwxrwx    6 root     root          4096 Apr  6 06:38 .git
 -rw-rw-rw-    1 root     root           190 Apr  6 06:38 .gitlab-ci.yml
 drwxr-xr-x    2 root     root          4096 Apr  6 06:38 cache
 $ ls -la cache
 total 12
 drwxr-xr-x    2 root     root          4096 Apr  6 06:38 .
 drwxrwxrwx    4 root     root          4096 Apr  6 06:38 ..
 -rw-r--r--    1 root     root             6 Apr  6 06:38 hello.txt
 -rw-r--r--    1 root     root             0 Apr  6 06:38 tada
Running after_script
Saving cache
00:02
 Creating cache cache...
 cache: found 3 matching files
 No URL provided, cache will be not uploaded to shared cache server. Cache will be stored only locally.
 Created cache
Uploading artifacts for successful job
00:01
 Job succeeded
Mounting volume to check content
 $ docker volume ls
DRIVER              VOLUME NAME
local               runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
local               runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8

 $ docker run -it --rm -v runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70:/cache alpine:3.11 sh
/ # cd /cache/
/cache # ls -la
total 12
drwxr-xr-x    3 root     root          4096 Apr  6 06:38 .
drwxr-xr-x    1 root     root          4096 Apr  6 06:39 ..
drwx------    3 root     root          4096 Apr  6 06:38 root
/cache # cd root/
/cache/root # ls
playground
/cache/root # cd playground/
/cache/root/playground # ls
cache
/cache/root/playground # cd cache/
/cache/root/playground/cache # ls
cache.zip
/cache/root/playground/cache # unzip cache.zip
Archive:  cache.zip
   creating: cache/
  inflating: cache/hello.txt
  inflating: cache/tada
/cache/root/playground/cache # ls -la
total 16
drwx------    3 root     root          4096 Apr  6 06:39 .
drwx------    3 root     root          4096 Apr  6 06:38 ..
drwxr-xr-x    2 root     root          4096 Apr  6 06:39 cache
-rw-------    1 root     root           559 Apr  6 06:38 cache.zip
/cache/root/playground/cache # cd cache/
/cache/root/playground/cache/cache # ls -la
total 12
drwxr-xr-x    2 root     root          4096 Apr  6 06:39 .
drwx------    3 root     root          4096 Apr  6 06:39 ..
-rw-r--r--    1 root     root             6 Apr  6 06:39 hello.txt
-rw-r--r--    1 root     root             0 Apr  6 06:39 tada
/cache/root/playground/cache/cache # cat hello.txt
hello

Cache (cache_dir defined)

config.toml
[[runners]]
  name = "docker"
  url = "http://192.168.144.160:3000"
  token = "ixxx"
  executor = "docker"
  environment = ["IMAGE=alpine"]
  cache_dir = "/steve-cache"
  [runners.docker]
    tls_verify = false
    image = "alpine:3.11"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/steve-cache"]
    shm_size = 0
.gitlab-ci.yml
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
  - cache

job:
  stage: test
  script:
  - mkdir -p cache
  - touch cache/tada
  - echo "hello" > cache/hello.txt
  - ls -la
  - ls -la cache
job log
 Running with gitlab-runner development version (HEAD)
   on docker fL_5iHR7
Preparing the "docker" executor
00:03
 Using Docker executor with image alpine:3.11 ...
 Pulling docker image alpine:3.11 ...
 Using docker image sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72 for alpine:3.11 ...
Preparing environment
00:01
 Running on runner-fl5ihr7-project-19-concurrent-0 via steve-mbp-gitlab.local...
Getting source from Git repository
00:02
 Fetching changes with git depth set to 50...
 Reinitialized existing Git repository in /builds/root/playground/.git/
 Checking out 373eee15 as cache...
 Removing cache/
 Skipping Git submodules setup
Restoring cache
 Checking cache for cache...
 No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
 Successfully extracted cache
Downloading artifacts
00:01
Running before_script and script
 $ mkdir -p cache
 $ touch cache/tada
 $ echo "hello" > cache/hello.txt
 $ ls -la
 total 20
 drwxrwxrwx    4 root     root          4096 Apr  6 06:46 .
 drwxrwxrwx    4 root     root          4096 Apr  6 06:18 ..
 drwxrwxrwx    6 root     root          4096 Apr  6 06:46 .git
 -rw-rw-rw-    1 root     root           190 Apr  6 06:38 .gitlab-ci.yml
 drwxr-xr-x    2 root     root          4096 Apr  6 06:46 cache
 $ ls -la cache
 total 12
 drwxr-xr-x    2 root     root          4096 Apr  6 06:46 .
 drwxrwxrwx    4 root     root          4096 Apr  6 06:46 ..
 -rw-r--r--    1 root     root             6 Apr  6 06:46 hello.txt
 -rw-r--r--    1 root     root             0 Apr  6 06:46 tada
Running after_script
00:01
Saving cache
00:01
 Creating cache cache...
 cache: found 3 matching files
 No URL provided, cache will be not uploaded to shared cache server. Cache will be stored only locally.
 Created cache
Uploading artifacts for successful job
00:02
 Job succeeded
Mounting volume to check content
 ~ docker volume ls
DRIVER              VOLUME NAME
local               runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
local               runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8
local               runner-fl5ihr7-project-19-concurrent-0-cache-e266396b86a4462bea9ff3ba0fe40fa0

 ~ docker run -it --rm -v runner-fl5ihr7-project-19-concurrent-0-cache-e266396b86a4462bea9ff3ba0fe40fa0:/steve-cache alpine:3.11 sh
/ # cd /steve-cache/
/steve-cache # ls -la
total 12
drwxr-xr-x    3 root     root          4096 Apr  6 06:46 .
drwxr-xr-x    1 root     root          4096 Apr  6 06:47 ..
drwx------    3 root     root          4096 Apr  6 06:46 root
/steve-cache # cd root/playground/
/steve-cache/root/playground # ls -la
total 12
drwx------    3 root     root          4096 Apr  6 06:46 .
drwx------    3 root     root          4096 Apr  6 06:46 ..
drwx------    2 root     root          4096 Apr  6 06:46 cache
/steve-cache/root/playground # cd cache/
/steve-cache/root/playground/cache # ls -la
total 12
drwx------    2 root     root          4096 Apr  6 06:46 .
drwx------    3 root     root          4096 Apr  6 06:46 ..
-rw-------    1 root     root           559 Apr  6 06:46 cache.zip
/steve-cache/root/playground/cache # unzip cache.zip
Archive:  cache.zip
   creating: cache/
  inflating: cache/hello.txt
  inflating: cache/tada
/steve-cache/root/playground/cache # cd cache/
/steve-cache/root/playground/cache/cache # cat hello.txt
hello

Services (Linux)

config.toml
[[runners]]
  name = "docker"
  url = "http://192.168.144.160:3000"
  token = "xxxx"
  executor = "docker"
  environment = ["IMAGE=alpine"]
  [runners.docker]
    tls_verify = false
    image = "alpine:3.11"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
.gitlab-ci.yml
job:
  image: alpine:3.11
  variables:
    SLEEP: 0
    POSTGRES_HOST_AUTH_METHOD: "trust"
  services:
  - name: postgres:12.2-alpine
    alias: db
  before_script:
  - echo $FF_NETWORK_PER_BUILD
  - apk add --no-cache postgresql-client
  script:
  - pg_isready -h db
  - pg_isready -h postgres
  - sleep ${SLEEP}
volumes mounted to service
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
d29b2ae323bc        a187dde48cd2        "sh -c 'if [ -x /usr…"   3 seconds ago       Up 2 seconds                                 runner-fl5ihr7-project-19-concurrent-0-build-1586158016
b2079af66864        ecb176ff304a        "docker-entrypoint.s…"   17 seconds ago      Up 15 seconds       5432/tcp                 runner-fl5ihr7-project-19-concurrent-0-postgres-0
c659b3e6cf84        registry:2          "/entrypoint.sh /etc…"   About an hour ago   Up About an hour    0.0.0.0:5000->5000/tcp   quizzical_rhodes

 ~ docker inspect b2079af66864 | jq .[].Mounts
[
  {
    "Type": "volume",
    "Name": "runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70",
    "Source": "/var/lib/docker/volumes/runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70/_data",
    "Destination": "/cache",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8",
    "Source": "/var/lib/docker/volumes/runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8/_data",
    "Destination": "/builds",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "5dac8041a908a15165a180c5980606bb7fe95b9ef6037084cd789feb0fd7e421",
    "Source": "/var/lib/docker/volumes/5dac8041a908a15165a180c5980606bb7fe95b9ef6037084cd789feb0fd7e421/_data",
    "Destination": "/var/lib/postgresql/data",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

 ~ docker volume ls
DRIVER              VOLUME NAME
local               5dac8041a908a15165a180c5980606bb7fe95b9ef6037084cd789feb0fd7e421
local               runner-fl5ihr7-project-19-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
local               runner-fl5ihr7-project-19-concurrent-0-cache-c33bcaa1fd2c77edfc3893b41966cea8

Services (Windows)

config.toml
[[runners]]
  name = "windows-docker"
  url = "http://192.168.144.160:3000"
  token = "xxx"
  executor = "docker-windows"
  [runners.docker]
    tls_verify = false
    image = "mcr.microsoft.com/windows/servercore:1809"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["c:\\cache"]
    pull_policy = "if-not-present"
    shm_size = 0
    helper_image = "gitlab/gitlab-runner-helper:x86_64-latest-servercore1809"
.gitlab-ci.yml
job:
  image: mcr.microsoft.com/windows/servercore:1809
  variables:
    SLEEP: 0
  services:
  - name: mcr.microsoft.com/dotnet/core/samples:aspnetapp
    alias: db
  script:
  - sleep ${SLEEP}
  - Invoke-WebRequest http://db -UseBasicParsing
volumes mounted to service
PS C:\Users\Administrator> docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
09db551dcd2e        73d9a9b9c9fb        "PowerShell -NoProfi…"   18 seconds ago       Up 16 seconds                           runner-lnguusc8-project-19-concurrent-0-build-1586158499
671b6f4d5e77        de13b3a2b98b        "dotnet aspnetapp.dll"   About a minute ago   Up About a minute                       runner-lnguusc8-project-19-concurrent-0-mcr.microsoft.com__dotnet__core__samples-0

PS C:\Users\Administrator> docker inspect 671b6f4d5e77

...
        "Mounts": [
            {
                "Type": "volume",
                "Name": "runner-lnguusc8-project-19-concurrent-0-cache-256a2a0a21f7076b19809f2a24b91cbb",
                "Source": "C:\\ProgramData\\docker\\volumes\\runner-lnguusc8-project-19-concurrent-0-cache-256a2a0a21f7076b19809f2a24b91cbb\\_data",
                "Destination": "c:\\cache",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "runner-lnguusc8-project-19-concurrent-0-cache-cde2929a41401004cf47d36bdb2eb380",
                "Source": "C:\\ProgramData\\docker\\volumes\\runner-lnguusc8-project-19-concurrent-0-cache-cde2929a41401004cf47d36bdb2eb380\\_data",
                "Destination": "c:\\builds",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...

Locally mounted file

config.toml
[[runners]]
  name = "docker"
  url = "http://192.168.144.160:3000"
  token = "xxx"
  executor = "docker"
  environment = ["IMAGE=alpine"]
  [runners.docker]
    tls_verify = false
    image = "alpine:3.11"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache", "/tmp/hello.txt:/workspace/hello.txt"]
    shm_size = 0
.gitlab-ci.yml
job:
  image: alpine:3.11
  script:
  - ls -la
  - cat /workspace/hello.txt
job log
 Running with gitlab-runner development version (HEAD)
   on docker fL_5iHR7
Preparing the "docker" executor
 Using Docker executor with image alpine:3.11 ...
 Pulling docker image alpine:3.11 ...
 Using docker image sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72 for alpine:3.11 ...
Preparing environment
00:01
 Running on runner-fl5ihr7-project-19-concurrent-0 via steve-mbp-gitlab.local...
Getting source from Git repository
00:02
 Fetching changes with git depth set to 50...
 Reinitialized existing Git repository in /builds/root/playground/.git/
 From http://192.168.144.160:3000/root/playground
  * [new ref]         refs/pipelines/349 -> refs/pipelines/349
  * [new branch]      local-volume       -> origin/local-volume
 Checking out dfc7da08 as local-volume...
 Skipping Git submodules setup
Restoring cache
00:01
Downloading artifacts
00:02
Running before_script and script
 $ ls -la
 total 20
 drwxrwxrwx    4 root     root          4096 Apr  6 07:48 .
 drwxrwxrwx    4 root     root          4096 Apr  6 07:00 ..
 drwxrwxrwx    6 root     root          4096 Apr  6 07:48 .git
 drwxrwxrwx    2 root     root          4096 Apr  6 07:48 .gitlab
 -rw-rw-rw-    1 root     root            76 Apr  6 07:48 .gitlab-ci.yml
 $ cat /workspace/hello.txt
 hello
Running after_script
00:01
Saving cache
Uploading artifacts for successful job
00:01
 Job succeeded

Locally mounted file with just read only (ro)

config.toml
[[runners]]
  name = "docker"
  url = "http://192.168.144.160:3000"
  token = "xxx"
  executor = "docker"
  environment = ["IMAGE=alpine"]
  [runners.docker]
    tls_verify = false
    image = "alpine:3.11"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache", "/tmp/hello.txt:/workspace/hello.txt:ro"]
    shm_size = 0
.gitlab-ci.yml
job:
  image: alpine:3.11
  script:
  - ls -la
  - cat /workspace/hello.txt
  - echo "job" > /workspace/hello.txt
job log
Running with gitlab-runner development version (HEAD)
   on docker fL_5iHR7
Preparing the "docker" executor
 Using Docker executor with image alpine:3.11 ...
 Pulling docker image alpine:3.11 ...
 Using docker image sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72 for alpine:3.11 ...
Preparing environment
00:02
 Running on runner-fl5ihr7-project-19-concurrent-0 via steve-mbp-gitlab.local...
Getting source from Git repository
00:01
 Fetching changes with git depth set to 50...
 Reinitialized existing Git repository in /builds/root/playground/.git/
 From http://192.168.144.160:3000/root/playground
  * [new ref]         refs/pipelines/350 -> refs/pipelines/350
    dfc7da0..322e7d8  local-volume       -> origin/local-volume
 Checking out 322e7d8a as local-volume...
 Skipping Git submodules setup
Restoring cache
00:02
Downloading artifacts
Running before_script and script
00:01
 $ ls -la
 total 20
 drwxrwxrwx    4 root     root          4096 Apr  6 09:11 .
 drwxrwxrwx    4 root     root          4096 Apr  6 07:00 ..
 drwxrwxrwx    6 root     root          4096 Apr  6 09:11 .git
 drwxrwxrwx    2 root     root          4096 Apr  6 07:48 .gitlab
 -rw-rw-rw-    1 root     root           115 Apr  6 09:11 .gitlab-ci.yml
 $ cat /workspace/hello.txt
 hello
 $ echo "job" > /workspace/hello.txt
 /bin/sh: eval: line 92: can't create /workspace/hello.txt: Read-only file system
Running after_script
00:01
Uploading artifacts for failed job
00:02
 ERROR: Job failed: exit code 1

Does this MR meet the acceptance criteria?

  • Documentation created/updated
  • Added tests for this feature/bug
  • In case of conflicts with master - branch was rebased

What are the relevant issue numbers?

Edited by Steve Xuereb

Merge request reports