Docker Can't Write to Directory Mounted Using -V Unless It Has 777 Permissions

Docker can't write to directory mounted using -v unless it has 777 permissions

More recently, after looking through some official docker repositories I've realized the more idiomatic way to solve these permission problems is using something called gosu in tandem with an entry point script. For example if we take an existing docker project, for example solr, the same one I was having trouble with earlier.

The dockerfile on Github very effectively builds the entire project, but does nothing to account for the permission problems.

So to overcome this, first I added the gosu setup to the dockerfile (if you implement this notice the version 1.4 is hardcoded. You can check for the latest releases here).

# grab gosu for easy step-down from root
RUN mkdir -p /home/solr \
&& gpg --keyserver pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
&& curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.4/gosu-$(dpkg --print-architecture)" \
&& curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.4/gosu-$(dpkg --print-architecture).asc" \
&& gpg --verify /usr/local/bin/gosu.asc \
&& rm /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu

Now we can use gosu, which is basically the exact same as su or sudo, but works much more nicely with docker. From the description for gosu:

This is a simple tool grown out of the simple fact that su and sudo have very strange and often annoying TTY and signal-forwarding behavior.

Now the other changes I made to the dockerfile were these adding these lines:

COPY solr_entrypoint.sh /sbin/entrypoint.sh
RUN chmod 755 /sbin/entrypoint.sh
ENTRYPOINT ["/sbin/entrypoint.sh"]

just to add my entrypoint file to the docker container.

and removing the line:

USER $SOLR_USER

So that by default you are the root user. (which is why we have gosu to step-down from root).

Now as for my own entrypoint file, I don't think it's written perfectly, but it did the job.

#!/bin/bash

set -e

export PS1="\w:\u docker-solr-> "

# step down from root when just running the default start command
case "$1" in
start)
chown -R solr /opt/solr/server/solr
exec gosu solr /opt/solr/bin/solr -f
;;
*)
exec $@
;;
esac

A docker run command takes the form:

docker run <flags> <image-name> <passed in arguments>

Basically the entrypoint says if I want to run solr as per usual we pass the argument start to the end of the command like this:

docker run <flags> <image-name> start

and otherwise run the commands you pass as root.

The start option first gives the solr user ownership of the directories and then runs the default command. This solves the ownership problem because unlike the dockerfile setup, which is a one time thing, the entry point runs every single time.

So now if I mount directories using the -d flag, before the entrypoint actually runs solr, it will chown the files inside of the docker container for you.

As for what this does to your files outside the container I've had mixed results because docker acts a little weird on OSX. For me, it didn't change the files outside of the container, but on another OS where docker plays more nicely with the filesystem, it might change your files outside, but I guess that's what you'll have to deal with if you want to mount files inside the container instead of just copying them in.

Docker userns-remap cannot write to mounted directory

to answer your question, the best way is to use 'user namespace' feature of the docker engine.

here's an example of how to use.
let's say your host user is myuser with id 3000

add myuser:3000:65536 to your /etc/subuid and /etc/subgid files

update your /etc/docker/daemon.json with this:

{
"userns-remap": "myuser"
}

don't forget to restart your docker engine :)

and that's it , all files belonging to your myuser local account will belong to id 0 is your container and the opposite will true as well.

This should help you fix your issue.

Let me know

Change file permissions in mounted folder inside docker container on Windows Host

I had the same problem of not being able to change ownership even after using chown. And as I researched, it was because of NTFS volumes being mounted inside ext filesystem. So I used another approach.

The volumes internal to docker are free from these problems. So you can mount your file on internal docker volume and then create a hard symlink to that file inside your local folder wherever you want:

sudo ln $(docker volume inspect --format '{{ .Mountpoint }}' <project_name>_<volume_name>) <absolute_path_of_destination>

This way you can have your files in desired place, inside docker and without any permission issues, and you will be able to modify the contents of file as in the normal volume mount due to hard symlink.

Here is a working implementation of this process which mounts and links a directory. In case you wanna know about the details, see possible fix section in issue.

EDIT

Steps to implement this approach:

  1. Mount the concerned file in internal docker-volume(also known as named volumes).
  2. Before making hardlink, make sure volumes and concerned file are present there. To ensure this, you should have run your container at least once before or if you want to automate this file creation, you can include a docker run which creates the required files and exits.

    docker run --rm -itd \
    -v "<Project_name>_<volume_name>:/absolute/path" \
    <image> bash -c "touch /absolute/path/<my_file>"

This docker run will create volumes and required files. Here, container is my project name, by default, it is the name of the folder in which project is present and <volume_name> is the same as one which we want to use in our original container. <image> can be the same one which is already being used in your original containers.


  1. Create a hardlink in your OS to the actual file location on your system. You can find the file location using docker volume inspect --format '{{ .Mountpoint }}' <project_name>_<volume_name>/<my_file>. Linux users can use ln in terminal and windows users can use mklink in command prompt.

In step 3 we have not used /absolute/path since the <volume_name> refers to that location already, and we just need to refer to the file.



Related Topics



Leave a reply



Submit