Search code examples
dockerdockerfilegitlab-cigitlab-ci-runneropenafs

Mount OpenAFS host volume in GitLab-CI runner to make it accesible in Docker


We have setup a CentOS 7 repository in OpenAFS that we access from our images to install some applications. This process is entirely manual and we're trying to automate the generation with GitLab-CI.

I've set up a runner following the instructions for setting Docker-in-Docker runner.

Then, I've modified the /etc/gitlab-runner/config.toml file to specify an OpenAFS host volume (volumes entry):

concurrent = 1
check_interval = 0

[[runners]]
  name = "DinD builder"
  url = "https://gitlab.ch/ci"
  token = "7cf33172d567dd2504e988a78f64c3"
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "docker:latest"
    privileged = true
    disable_cache = false
    volumes = ["/afs:/afs:ro", "/cache"]
  [runners.cache]

In the Dockerfile, we have a RUN command that copies the repo file from AFS to the currently-being-built-image, so we can install the software with yum install:

FROM gitlab-registry.ch/cc7-base

MAINTAINER Somebody

RUN echo "set completion-ignore-case On" >> /etc/inputrc
RUN yum update -y && \
    yum install -y \
        gcc \
        git \
        mc \
        python-devel \
        python-pip \
        svn \
        unzip \
        vim

RUN cp /afs/<hugePathHere>/Linux/RPM/cc7/custom-repo.repo /etc/yum.repos.d && \
    yum install --enablerepo=custom-repo -y CustomApp

CMD /bin/bash

The .gitlab-ci.yml file is:

services:
  - docker:dind

build:
  stage: build
  tags:
    - rtf-builder
  before_script:
    - docker info
    - docker login -u $DOCKER_LOGIN_USERNAME -p $DOCKER_LOGIN_PASSWORD gitlab-registry.ch
  script:
    - docker build --pull -t $TO .
    - docker push $TO
  after_script:
    - docker logout gitlab-registry.ch
  variables:
    TO: gitlab-registry.ch/<myUser>/testdockergitlabbuild:$CI_BUILD_REF_NAME

But this always fails, with GitLab-CI telling me that

cp: cannot stat '/afs/hugePathHere/Linux/RPM/cc7/custom-repo.repo': No such file or directory

  • In the host machine, AFS is accesible and I can manually copy the repo file.

  • A container created with docker run --rm --privileged -ti -v /afs:/afs cc7-base has AFS accesible.

Am I missing something to make AFS accesible from the Dockerfile?

NOTE:

$DOCKER_LOGIN_USERNAME and $DOCKER_LOGIN_PASSWORD are GitLab secure variables.


Solution

  • I found a way to have AFS and Docker together, but not with a Docker-in-Docker runner.

    The trick is to use instead a shell runner. So when registering the runner, we should do it like:

    sudo gitlab-ci-multi-runner register -n \
      --url <GITLAB_CI_SERVER_URL> \
      --registration-token <PROJECT_TOKEN> \
      --executor shell \
      --tag-list "shell-builder" \
      --description "Shell builder for Docker images"
    

    Afterwards, we just need to install Docker and make it available for the gitlab-runner user (for example, adding the user to the docker group).

    As stated here, we can't access the files inside AFS from the Dockerfile.

    Instead, we can use a 2-step build:

    1. Build with the Dockerfile everything that doesn't need to access AFS.
    2. Execute a script that will run a container from that image, with AFS mounted and install all the AFS related stuff.

    Then, we just have to commit the container and push it to the registry as the final image.


    As an example, the files involved in this process could be something like this:

    .gitlab-ci.yml

    stages:
      - build
    
    variables:
      TO: <GitLab Registry URL>/<project>:$CI_BUILD_REF_NAME
    
    build:
      stage: build
      tags:
        - shell-builder
      before_script:
        - docker login -u $DOCKER_LOGIN_USERNAME -p $DOCKER_LOGIN_PASSWORD <GitLab Registry URL>
      script:
        - docker build --pull -t $TO .
      after_script:
        - sh ./postBuild.sh $TO $GITLAB_USER_EMAIL
        - docker push $TO
        - docker logout <GitLab Registry URL>
    

    Dockerfile

    FROM <Some base image>
    
    MAINTAINER <Somebody>
    
    <Do everything not related to AFS>
    
    CMD /bin/bash
    

    postBuild.sh

    #!/bin/bash
    
    readonly imageName="$1"
    readonly maintainer="$2"
    
    readonly imageNameAsLatest="$imageName-latest"
    readonly containerName="afs_mounted"
    
    docker create -ti --privileged -v /afs:/afs --name="$containerName" "$imageName"
    docker start "$containerName"
    
    docker exec "$containerName" /bin/bash -c "cp /afs/LONG_AFS_PATH/Linux/CentOS7/custom-repo.repo /etc/yum.repos.d"
    docker exec "$containerName" /bin/bash -c "yum install --enablerepo=custom-repo -y CustomApplication"
    
    docker commit -a "$maintainer" -m "Mounted AFS in a container and installed CustomApplication." "$containerName" "$imageName"
    
    docker tag "$imageName" "$imageNameAsLatest"
    
    docker stop "$containerName"
    docker rm "$containerName"