Docker – how to set the image volume in gitlab-runner with docker executor

continuous integrationdockergitlab

Okay, so I've researched all over for this and can't seem to find a definitive answer.

I want to know how gitlab-runner docker executor sets the volumes for the image. I see from the second URL I posted you can put the directory on the host to be used by the image, the same way you would with the -v option in docker run, however it is an absolute path which can't work if running parallel jobs since the directory will change. However, I can't find if I can use $PWD for the build directory, or if that will work since the config.toml file is in a different location. The documentation from what I read does not specify how that would work, or if it could work. I'm trying to find some answers before I burn hours during the next sprint trying to get something to work that may or may not work. So hoping for some insight.

So my question is: has any one ran into this issue before and if so, how did you set it up so the build directory is the directory being passed to the docker image? The same way you would if running docker build with the '-v' option or docker compose using 'volume:'.

The reason I want to run the images in this fashion and not the shell executor, which is what I'm doing currently. Is because if you cancel a build, you have to go in and manually kill the images on the runner's server. As you may imagine this can be annoying and time consuming if there are multiple builds in progress.

I also wish to avoid creating a custom docker image, because I do not want to put the git repository in the docker image. I only want to make additional docker images, that are reusable across CI/CD repositories so I don't want to add that as a command in a shell script that will be copied into the image and hence make the image none reusable.

If the above is not possible, is there a way to 'export' the directory as a variable to the docker image? I don't think there is since docker has to pass the volume to the image at startup.

I also don't want to have to build the docker image every time I run a test in CI/CD since that can be time consuming and expensive. I'd rather pass the volume and run the commands needed to do the test.

The command if running in shell script:
$ docker run -d -p 80:80 –name my-apache-php-app -v "$PWD":/var/www/html php:7.0-apache

Hopefully, this is the right forum for this question, wasn't sure if this fall under stackoverflow or serverfault.

After further research, it looks as if the runner actually runs the git commands in the docker container that is listed as the image and links the services to it. However, super confusing because they don't really spell this step out, so I still don't know if it is running the git commands in the build directory for the host or the container, if it's the container then I need to update the docker file.

references:

https://docs.gitlab.com/runner/executors/docker.html

https://docs.gitlab.com/runner/configuration/advanced-configuration.html#volumes-in-the-runners-docker-section

Best Answer

The answer is... it clones to the build directory in the image, by creating the directory and then cloning to it, much like calling docker exec. So when you are running commands you are running them in the build container, that containers image is set with the 'image:' key. So in order to get scripts from the host system into the build container, you will have to set the volume from the host to the build container. So I put an extra directory in my image, I called it tools_for_ci, then I mount a directory with all those scripts to the image. This works great. The issue now arises, that the docker image can not talk back and forth with the services. This is a known hindrance with docker executor, with no improvement in site, all the issues I have seen are marked backlog. So unfortunately it does not look like a fix will be implemented for that any time soon.

So in short, the image gets all the files it needs from the repo at run time, which means you do not need to set a volume, unless you are transferring scripts from the host to the image. All script commands are also executed on the image.

However, docker in docker, when binded to the docker socket, does appear to save the images so you don't have to re-download every time. So I may try that to get around the issue with the back and forth communication between the image and the services.