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

Disclaimer/Edit 2
Some years later, for everyone reading this question - If you are on Windows and want to use docker with linux containers, I highly recommend not using docker for windows at all and instead starting the entire docker environment inside a VM altogether. This Ext3 NTFS issue will break your neck on so many different levels that installing docker-machine might not even be worth the effort.
Edit:
I am using docker-machine which starts a boot2docker instance inside a Virtualbox VM with a shared folder on /c/Users from which you can mount volumes into your containers. The permissions of said volumes are the ones the question is about. The VMs are stored under /c/Users/tom/.docker/
I chose to use the docker-machine Virtualbox workflow over Hyper-V because I need VBox in my daily workflow and running Hyper-V and Virtualbox together on one system is not possible due to incompabilities between different Hypervisors.
Original question
I am currently trying to set up PHPMyAdmin in a container on windows but I can't change the permissions of the config.inc.php file.
I found: Cannot call chown inside Docker container (Docker for Windows) and thought this might be somewhat related but it appears to apply only to MongoDB.
This is my docker-compose.yml
version: "3"
services:
pma:
image: (secrect company registry)/phpmyadmin
ports:
- 9090:80
volumes:
- /c/Users/tom/projects/myproject/data/var/www/public/config.inc.php:/var/www/public/config.inc.php
now, when I docker exec -it [container] bash and change in the mounted directory, I try to run chmod on the config.inc.php but for some reason, it fails silently.
root#22a4bag43245: ls -la config.inc.php
-rw------- 1 root root 0 Aug 11 15:11 config.inc.php
root#22a4bag43245: chmod 655 config.inc.php
root#22a4bag43245: ls -la config.inc.php
-rw------- 1 root root 0 Aug 11 15:11 config.inc.php
Considering the linked answer, I thought I could just move the volume out of my Userhome but then vbox doesn't mount the folder at all.
How do I change the file permissions of /var/www/public/config.inc.php persistently?

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:
Mount the concerned file in internal docker-volume(also known as named volumes).
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.
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.

Try one of the following:
If you can rebuild the image image: image: (secrect company registry)/docker-stretchimal-apache2-php7-pma then inside the docker file, add the following
USER root
RUN chmod 655 config.inc.php
Then you can rebuild the image and push it to the registry, and what you were doing should work. This should be your preferred solution, as you don't want to be manually changing the permissions everytime you start a new container
Try to exec using the user root explicitly
docker exec -it -u root [container] bash

Related

Change mountpoint of docker volume to a custom directory

I would like to have a Docker Volume that mounts to a container. This volume would need to be somewhere other than the default location of volumes, preferably somewhere on the Desktop. This is because I am running a web server and would like some directories to be editable by something like VSCode so I don't always have to go inside the container to edit a file. I am not going to be using Docker Compose and instead will be using a Docker File for the container. The functionality I'm going for is the following equivalent of Docker Compose, but in a Dockerfile or through docker run, whichever is easiest to accomplish:
volumes:
- <local-dir>:<container-dir>
This directory will need to be editable LIVE and using the Dockerfile ADD command will not suffice, because after building, the image gets put into a tar archive and cannot be accessed after that.
with this solution you can move even A live container to new partition:
Add a configuration file to tell the docker daemon what is the location of the data directory
Using your preferred text editor add a file named daemon.json under the directory /etc/docker. The file should have this content:
{
"data-root": "/path/to/your/docker"
}
Copy the current data directory to the new one
sudo rsync -aP /var/lib/docker/ /path/to/your/docker
Rename the old docker directory
sudo mv /var/lib/docker /var/lib/docker.old
Restart the docker daemon
sudo service docker start
resource: https://www.guguweb.com/2019/02/07/how-to-move-docker-data-directory-to-another-location-on-ubuntu/
You can mount a directory from your host inside your container when you launch the docker container, using -v or --volume
docker run -v /path/to/desktop/some-dir:/container-dir/path <docker-image>
Volumes specified in the Dockerfile, as you exemplified, will automatically create those volumes under /var/lib/docker/volumes/ every time a container is launched from that image, but it is NOT recommended have these volumes altered by non-Docker processes.

Docker volume bind empty volume or convert files to folders

I'm running a container by sending to docker daemon so it can run a sibling container and in that container I try to run another container and mount a volume to access some data, however in the sibling container, the volume is either empty or the file is converted to a folder...
Running the first container:
$ docker run -v /var/run/docker.sock:/var/run/docker.sock -it example /bin/bash
root#3aa35965846a:/home/node/example# ls some_volume/
test.txt
root#3aa35965846a:/home/node/example# cat some_volume/test.txt
hello
// Running the second container
root#3aa35965846a:/home/node/example# docker run -v /home/node/example/some_volume/:/some_volume/ -it node:10 /bin/bash
root#6a84739fbb92:/# ls /some_volume/
* test.txt
root#6a84739fbb92:/# cat /some_volume/test.txt/
cat: /some_volume/test.txt/: Is a directory
The first time I run the second container the volume is empty, if I try to mount a file directly it is converted to a folder, and after that if I try to mount the folder like the example above, there is only the file I tried to mount earlier and it is a folder.
How is this possible ? If i try to mount a volume outside the first container I don't have any problem, how can I fix this ?
The first path in the docker run -v option is always on the host system. For example, if you
docker run -v /etc:/x busybox cat /x/shadow
it will dump out the host's encrypted password file, regardless of whether you ran this command directly from the host or from a container.
There isn't a way to share an arbitrary directory from one container to another. If the launching container knows something about its own directory structure (in particular that some directory was mounted from a specific host path or named volume) then it can replicate that to the other container, but that's not a generic answer. The other behaviors you're seeing are just a consequence of those directories not existing on the host system.
In general I would advise not using Docker for short-lived processes that principally interact with the outside world through the filesystem. Take whatever program you'd run in the other container, install it in your image's Dockerfile, and run it directly without going through Docker.
If you really can't avoid this workflow, the only thing I've found to work reliably is to docker create the container, docker cp files in, docker start it, and docker wait for it to finish. When it's done, docker cp the result out before docker rm it. That's a kind of painstaking workflow but it gets around the problem of the two containers not sharing any filesystem space.

Volume mount not writing out to host machine

I'm trying to set up my docker container with a host machine directory mounted to the container for writing logs out to. My dockerfile is pretty simple:
FROM golang:1.9.2
WORKDIR /
COPY daemon /
CMD ["./daemon", "-d", "debug"]
Where daemon is the compiled binary of a Go program. I'm starting the container via the following command:
docker run -d --restart unless-stopped -v /var/log/scope/:/var/log/scope/ slack_daemon
Where slack_daemon is the name of the image the above dockerfile is built into.
However, the directory /var/log/scope in the container is not being written out to the host machine. Anything I place in that directory on the host machine is visible inside the container, but neither writing to existing files or creating new files in that directory in the container is writing out to the host machine. No error is being thrown by docker or any of the commands, it just simply isn't writing anything out to the host directory.
Running Docker 17.09.0-ce-mac35, stable channel, on OSX 10.12.6.
Things I've tried:
Running the docker run command as sudo.
Adding the --privileged flag to docker run.
chmod 777 on /var/log/scope on the host machine.
I specifically need that directory in both host and container, as our code and log handler both expect that location and it would be too large of a change for this current issue to alter that.
Any guidance on this would be appreciated. Most of the sources online that I can find suggest that this is an SELinux issue, but I'm not getting the "permission denied" error, and this is OSX, not linux.
I've also checked on the /var dir itself. It aliases to /private/var:
lrwxr-xr-x# 1 root wheel 11 Oct 30 10:54:11 2017 var -> private/var
And /private is by default a shared directory within the file sharing settings in docker.

Change volume configuration in docker-compose without losing the data

My docker-compose has a data container which isn't mapped to a local directory in the host machine, and I want to change it from:
volumes:
- /var/www/html
to
volumes:
- /html:/var/www/html
But when I will restart the container, it will remove the current data container and replace it with a new one.
I know that the container is actually still there, but is there an easy way to do it without the creation of a new data container.
My docker-compose version is 1.7.1 (under boot2docker).
Thanks.
Try at your own risk:
create your host directory /htmlas you wish
docker inspect {container_name} | grep Source and grab your volume path on the host system. It'll be something like /var/lib/docker/volumes/abdb15a2eff[...]/_data
copy the content of that directory to your host directory
recreate the container as you wish.
One safe way to do this is to create a backup of the data from inside the Docker image. Then restore that backup to the directory on your host machine. The Docker Volumes Tutorial mentions a process like this near the bottom.
Here's how you'd do it:
First, mount a directory from your host machine into the container if you don't already have one mounted in. Maybe a volume like ./:/backup. Next, run a backup command like this:
docker-compose run service-name tar czvf /backup/html_data.tar.gz /var/www/html
Now you have html_data.tar.gz in your current directory. Extract it wherever you want and be on your way!
(I'm assuming, based on the way you indicated your volumes, that you're using docker-compose. The process is similar for vanilla Docker.)
Alternate approach, with --volumes-from
Get the name (or hash) of the container with the data you want to copy. You can do this with docker ps. For this example, let's call it container1. Now run this command to back up its data:
docker run --rm --volumes-from container1 -v $(pwd):/backup ubuntu:latest tar czvf /backup/html_data.tar.gz /var/www/html
Note that the image you use (ubuntu:latest) is not important as long as it can tar things.

Docker container doesn't see files on windows volumes when the volume endpoint isn't on the drive C:

I want to use a docker image in my work process. For example I want to use larryprice/sass to compile my SASS files to CSS. This image is pretty simple:
FROM ruby:2.2
RUN gem install sass
WORKDIR /tmp
ENTRYPOINT ["sass", "--watch", "/src"]
I'm using Windows 10, Docker 1.11 and VirtualBox 5.0.16.
My project files placed on work SSD, that mapped to logical drive D -
D:\Projects\Foo\Bar\web\sass
So, my problem is following: when I attach a volume to the container from drive D: (by $PWD or by full path in MINGW style /D/Projects/Foo/Bar/web/sass) e.g.
cd /D/Projects/Foo/Bar/web
docker run --name sass -v $PWD/sass:/src --rm larryprice/sass
the container can't see any SASS files:
$ docker exec -i -t sass /bin/bash
root#541aabac9ceb:/tmp# ls -al /src/
total 4
drwxr-xr-x 2 root root 40 May 3 13:05 .
drwxr-xr-x 50 root root 4096 May 3 13:05 ..
But when I mount a volume from system disk (C:) all works fine:
$ docker run --name sass -v ~/sass:/src --rm larryprice/sass
[Listen warning]:
Listen will be polling for changes. Learn more at https://github.com/guard/listen#polling-fallback.
>>> Sass is watching for changes. Press Ctrl-C to stop.
>>> New template detected: ../src/test.sass
write /src/test.css
write /src/test.css.map
How I can mount volumes from any place I need in Windows? Or what I'm doing wrong in my case?
p.s. Add leading slash to the path also not working:
docker run --name sass -v //d/Projects/Foo/Bar/web/sass:/src --rm larryprice/sass
Okay. Finally I found an explanation and solution for my own question. This solution will work for both Windows and MacOS X (because both of them uses VirtualBox to make Docker do the things).
The source of the problem consists from two points:
By default, VirtualBox VM have limited access to the host filesystem (proof). In my case it have access to the users folder on drive C: via VBox shared folder (screen). Thank to this, I can use volumes mapping like this one: ~/sass:/src (or full path: /c/users/dbykadorov/sass). Unfortunately, this configuration not allows me to use any path outside from /c/users/.
Solution for this point: add another shared folder to the VM, pointed on directory I need. I created new share d:/Projects (screen). Reboot your VM.
I hope here you'll complete your case. But in my case, VirtualBox does not mount new shared folder at system startup. So, I got second problem:
VirualBox does not mount additional shared folder, that I just added.
Additional solution:
Let's try to mount shared folder manually. Log into VM by any available ways. In console:
# Create mount point directory
$ mkdir -p /d/Projects
# Mount shared folder
$ mount -t vboxsf d/Projects /d/Projects
Okay, this do the trick! Now I can mount any project's directory (within D:\Projects)!
But... when I'll reboot my VM the mountpoint will disappear =( Now we need to make our mount point more persistent. As described here:
# Make a file bootlocal.sh
$ touch /var/lib/boot2docker/bootlocal.sh
# Edit it
$ vi /var/lib/boot2docker/bootlocal.sh
# Add follovin lines here:
#!/bin/sh
mkdir -p /d/Projects
mount -t vboxsf d/Projects /d/Projects
# Save the file and reboot VM
Important note: to make volumes creating more clear it will be good idea to mount shared folder to the same path as on the host. E.g. if we need to create volumes from E:\Foo\Bar\Baz (/e/Foo/Bar/Baz in MINGW style) then we need to add new shared folder for E:\Foo\Bar\Baz and mount it exactly to /e/Foo/Bar/Baz in your Docker VM.
That is All.

Resources