floatingpurr
floatingpurr

Reputation: 8599

Jenkins in Docker: clarification about bind mounts in pipelines

I'm running Jenkins in a Docker container. Following this article, I'm bind mounting the Docker socket in order to interact with it from the dockerized Jenkins. I'm also bind mounting the container directory jenkins_home. Here is a quick recap on my volumes:

# Jenkins
volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro
  - /usr/local/bin/docker-compose:/usr/local/bin/docker-compose
  - ./bar:/var/jenkins_home

I run this from the directory /home/foo/ of the host, therefore the following directory is created in the host file system (and mounted):

/home/foo/bar

Now, I have a Jenkins pipeline (mypipe) that runs a docker-compose file spinning up a MySQL container with the following volume:

# MySQL created from Jenkins
volumes:
  - ./data:/var/lib/mysql

Weirdly enough, it ends up mounting:

/var/jenkins_home/workspace/mypipe/data < /var/lib/mysql

instead of:

/home/foo/bar/workspace/mypipe/data < /var/lib/mysql

Here is a graphical recap:

enter image description here

Searching stackoverflow, it turned out that it happens since:

The volume source path (left of :) does not refer to the middle container, but to the host filesystem!

And that's ok, but my question is:

Why there?

I mean why does .data is translated exactly into the path: /var/jenkins_home/workspace/…/data, since the MySQL container is not aware of the path /var/jenkins_home?

Upvotes: 1

Views: 1699

Answers (1)

David Maze
David Maze

Reputation: 159722

When Docker creates a bind mount, it is always from an absolute path in the host filesystem to an absolute path in the container filesystem.

When your docker-compose.yml names a relative path, Compose first expands that path before handing it off to the Docker daemon. In your example, you're trying to bind-mount ./bar from a file /var/jenkins_home/workspace/mypipe/docker-compose.yml, so Compose fills in the absolute path you see when it invokes the Docker API. Compose has no idea that the current directory is actually a bind-mount from a different path in the Docker daemon's context.

If you look in the Jenkins logs at what scripted pipeline invocations like docker.inside { ... } do, mounts the workspace directory to an identical path inside the container it launches. Probably the easiest way to work around the mapping problem you're having is to use an identical /var/jenkins_home path on the host system, so the filesystem path is the same in every context.

Upvotes: 2

Related Questions