0

I want my Dockerfile to mkdir .ssh/
But it does not, why not?

FROM jenkinsci/jnlp-slave

MAINTAINER Johnny5 isAlive <johnny5@hotmail.com>

USER root

RUN rm /bin/sh && ln -s /bin/bash /bin/sh

RUN apt-get update
RUN apt-get install unzip git curl vim -y

USER jenkins

RUN mkdir -p /home/jenkins/.ssh && touch /home/jenkins/.ssh/aFile

...building... Looks fine?

Step 12 : RUN mkdir -p /home/jenkins/.ssh && touch /home/jenkins/.ssh/aFile
 ---> Running in ca19a679580d
 ---> 5980df7db482
Removing intermediate container ca19a679580d
Successfully built 5980df7db482

Running and looking around, the .ssh/ folder and aFile inside are not there ...

$ docker run -it -u 0 --entrypoint /bin/bash 5980df7db482
root@4aa40a18baf2:~# pwd
/home/jenkins
root@4aa40a18baf2:~# ls -al
total 24
drwxr-xr-x 3 jenkins jenkins 4096 Oct 17 23:17 .
drwxr-xr-x 4 root    root    4096 Sep 14 08:50 ..
-rw-r--r-- 1 jenkins jenkins  220 Nov 12  2014 .bash_logout
-rw-r--r-- 1 jenkins jenkins 3515 Nov 12  2014 .bashrc
-rw-r--r-- 1 jenkins jenkins  675 Nov 12  2014 .profile
drwxr-xr-x 2 jenkins jenkins 4096 Sep 14 08:50 .tmp
root@4aa40a18baf2:~# 
Johnny5
  • 463
  • 2
  • 5
  • 16
  • 3
    What lines didn't you include from your Dockerfile? Show the full output. Because the provided file shouldn't be on step 12. Also, don't run apt-get update on a separate run line from apt-get install. There's a [best practices](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#run) entry for that. – BMitch Oct 17 '16 at 23:52
  • Looks like you're trying to build a Jenkins build slave. You might want to check out [Dockins](http://dockins.github.io/). It's still early in development, but may give you some ideas. – Roman Oct 18 '16 at 01:14

1 Answers1

5

If I pull the parent image, jenkinsci/jnlp-slave, and inspect it with docker inspect jenkinsci/jnlp-slave, I can see that it already has a volume defined at /home/jenkins:

[
    {
        ...
        "ContainerConfig": {
            ...
            "Volumes": {
                "/home/jenkins": {}
            },
        ...
    }
]

This means that during each build step, any changes you make to that location won't be committed to your new layer.

Here's a simplified version of your Dockerfile to highlight what's going on:

FROM jenkinsci/jnlp-slave
RUN mkdir -p /home/jenkins/.ssh

Now, let's build with the following command: docker build --no-cache --rm=false -t jns .:

Sending build context to Docker daemon  2.56 kB
Step 1 : FROM jenkinsci/jnlp-slave
 ---> d7731d944ad7
Step 2 : RUN mkdir -p /home/jenkins/.ssh
 ---> Running in 520a8e2f7cae
 ---> 962189878d5e
Successfully built 962189878d5e

The --no-cache option makes the command easier to work with on repeat invocations. The --rm=false will cause the builder to not remove the containers created for each step.

In this case, the builder ran the Step 2 in 520a8e2f7cae on my system. I can now do a docker inspect 520a8e2f7cae and see the actual container used for this step. Specifically, I'm curious about the mounts location:

[
    {
    ...
    "Mounts": [
        {
        "Name": "e34fd82bd190f21dbd63b5cf70167a16674cd00d95fdc6159314c25c6d08e10e",
        "Source": "/var/lib/docker/volumes/e34fd82bd190f21dbd63b5cf70167a16674cd00d95fdc6159314c25c6d08e10e/_data",
        "Destination": "/home/jenkins",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
        }
    ],
    ...
    }
]

I see that there's an anonymous volume with id e34fd82bd190f21dbd63b5cf70167a16674cd00d95fdc6159314c25c6d08e10e for /home/jenkins.

I can inspect the contents of that volume like this:

$ docker run --rm -v e34fd82bd190f21dbd63b5cf70167a16674cd00d95fdc6159314c25c6d08e10e:/volume alpine ls -lah /volume
total 28
drwxr-xr-x    4 10000    10000       4.0K Oct 18 02:49 .
drwxr-xr-x   25 root     root        4.0K Oct 18 02:55 ..
-rw-r--r--    1 10000    10000        220 Nov 12  2014 .bash_logout
-rw-r--r--    1 10000    10000       3.4K Nov 12  2014 .bashrc
-rw-r--r--    1 10000    10000        675 Nov 12  2014 .profile
drwxr-xr-x    2 10000    10000       4.0K Oct 18 02:49 .ssh
drwxr-xr-x    2 10000    10000       4.0K Sep 14 08:50 .tmp

The .ssh directory created in the RUN step is in this volume. Since volumes aren't part of the container's write layer, it won't get committed. I can confirm this by doing a docker diff on this container:

docker diff 520a8e2f7cae

There is no output, showing no changes to the container's filesystem, which is why it doesn't come forward into this layer of the image.

The other contents at this location are files in the parent image that were committed before the VOLUME directive that made /home/jenkins into a volume.

programmerq
  • 6,262
  • 25
  • 40
  • Great thanks! ... and so to get the folder created, I went backwards through the Dockerfiles, found where the volume was mounted, and before that added a RUN mkdir /home/jenkins/.ssh command – Johnny5 Oct 18 '16 at 19:32
  • another option would be to write at ENTRYPOINT script that would populate the .ssh folder in the volume. That way, you don't have to modify parent images. – programmerq Oct 19 '16 at 02:20