Docker is one of those development projects that lived up to the hype. It allows you to package and ship your application, without having to worry as much about the deployment environment.
Key phrase: “as much”
Unfortunately, it is no silver bullet. Take for instance the Jenkins’ docker repository. When you decided to use this to deploy your Jenkins instance, you probably executed:
docker run --name myjenkins -p 8080:8080 -p 50000:50000 -v /home/jenkins:/var/jenkins_home jenkins
And somewhere along the execution, you get something like this:
/usr/local/bin/jenkins.sh: line 25: /var/jenkins_home/copy_reference_file.log: Permission denied
Base on my experience, there are two culprits that cause this error. First is you mounted an inexistent volume. Second is a mismatch of uid and/or gid in the local machine and in the container.
Consider the Jenkins above for instance. If you managed to execute bash inside your Jenkins container before it quits (there are ways to ensure your container does not exit despite encountering error which I won’t cover in this post) and run
ls /var/jenkins_home you might get:
ls: cannot access 'asdf': No such file or directory
You need to fix your volume field, ensure that /home/jenkins exist on your local machine.
But I doubt this is the case for you. Sure clumsy your fingers might be, there is a conspiracy spawned by DevOps folks to stop developers like you and me to easily spin our own Continuous Integration instance. Or like me, you have never cared about how Linux handles read/write permissions.
Mismatch Of uid/gid
Executing a simple
ls -l you get something like:
total 16 drwxrwxr-x 2 jandres jandres 4096 Jul 16 02:29 blog drwxrwxr-x 3 jandres jandres 4096 Jul 16 02:04 ci drwxrwxr-x 3 jandres jandres 4096 May 18 17:30 osx-sierra-box drwxrwxr-x 4 jandres jandres 4096 May 18 18:03 vagrant-box-osx
What interest us here is the highlighted jandres jandres. It means the file is owned by user jandres and group jandres.
When Linux creates a user foo, it will automatically create and add a user to a group with the same name foo. In the case of the Jenkins docker repo, this would be user and group jenkins.
Now you might say,
but /home/jenkins is also owned by user=jenkins and group=jenkins
Now I introduce you to uid and gid. Linux doesn’t really see user=jandres and group=jandres when it sees the file above, but rather it sees uid=1000 and gid=1000. This mapping is indicated in /etc/passwd. In my case for instance, my jenkins user have the following line in /etc/passwd:
This simply means my user jenkins have a uid of 1002 (yours might differ, it doesn’t really matter). To find the guid of jenkins group, you simply do the same thing in /etc/group.
Going back to the Jenkins docker example above, despite /home/jenkins is owned by user=jenkins and group=jenkins in local machine and the same user=jenkins and group=jenkins in the container, their uid and gid might not match. For instance, in my local machine, the /etc/passwd and /etc/group indicated that uid=1002, and gid=1002, whilst this is uid=1000 and gid=1000 in the container. Hence the uid/gid mismatch!
The fix is easy enough. We just need to either use the same uid, which you can specify in a
docker run, via
-u. So in the example above, I would execute it via:
docker run -u 1002 --name myjenkins -p 8080:8080 -p 50000:50000 -v /home/jenkins:/var/jenkins_home jenkins
This tells docker container to use a user with uid 1002 to do the write operations.
That’s It! Tell me if it worked. Annoy me if it did not.