How can one open a GUI from within a Docker container - docker

I'm having difficulty opening a GUI from within a Docker container. As a test version of doing this, I've created the following Dockerfile:
FROM centos:7
RUN yum -y update
RUN yum -y install firefox
RUN yum -y install libcanberra-gtk-module
RUN yum -y install libcanberra-gtk3-module
RUN yum -y install gedit
CMD bash
I then used it to build an image in a straight-forward way:
(base) me#machine:~/firefox-test$ docker build -t firefox-test .
I was under the impression that in order to get the resulting container to work, I should use a Docker run command that would pass the correct value for the environmental variable DISPLAY and forward the X sockets to the resulting container:
docker run --rm -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix <image name>
However, even after disabling access control to I am not able to open Firefox from within the container:
(base) me#machine:~/firefox-test$ xhost +
access control disabled, clients can connect from any host
(base) me#machine:~/firefox-test$ docker run --rm -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix firefox-test
[root#fe740bde3923 /]# firefox
Error: cannot open display: :1
When I look at the contents of the mounted director, I see this:
[root#fe740bde3923 /]# ls -al /tmp/.X11-unix/
total 8
drwxr-xr-x 2 root root 4096 Jan 15 01:38 .
drwxrwxrwt 1 root root 4096 Jan 15 03:33 ..
which does not display the sockets included in the original directory (i.e. the one that my container should have mounted)
(base) me#machine:~/firefox-test$ ls -al /tmp/.X11-unix/
total 28
drwxrwxrwt 2 root root 4096 Dec 10 23:17 .
drwxrwxrwt 37 root root 20480 Jan 14 23:39 ..
srwxrwxrwx 1 root root 0 Dec 10 23:17 X0
srwxrwxrwx 1 root root 0 Dec 10 23:17 X1
Although, the Docker container's value of 1 for DISPLAY is correct:
(base) me#machine:~/firefox-test$ echo $DISPLAY
:1
Is my problem that I haven't managed to give my container access to the sockets? If so, how do I fix this? If not, what am I doing wrong?

Related

Can't change ownership of '/dev/gpiomem' in a docker container in RPi

I'm trying to run a simple docker container with a python base image to control the LEDs on my RPi4.
The Dockerfile compiles fine and I'm running it as follows:
docker run --rm -ti --privileged --device /dev/gpiomem:/dev/gpiomem -d led_blinker bash
Once inside the docker container I run a ls -l /dev/gpiomem and I get
root#ca1506d00cc5:/# ls -l /dev/gpiomem
crw-rw---- 1 nobody nogroup 246, 0 Dec 30 21:47 /dev/gpiomem
I try to do
root#ca1506d00cc5:/# chown root.root /dev/gpiomem
chown: changing ownership of 'dev/gpiomem': Operation not permitted
But when I run a whoami I get I'm the root user. What is that I'm missing?
PS. I have also added the flag --user root and got the same results.

Understanding Docker volumes

I am trying to learn Docker volumes, and I am using centos:latest as my base image. When I try to run a Docker command, I am unable to access the attached volume inside the container:
Command:
sudo docker run -it --name test -v /home/user/Myhostdir:/mydata centos:latest /bin/bash
Error:
[user#0bd1bb78b1a5 mydata]$ ls
ls: cannot open directory .: Permission denied
When I try to ls to find the folder permission, it says 1001. What's happening, and how can to solve this?
drwxrwxr-x. 2 1001 1001 38 Jun 2 23:12 mydata
My local machine:
[user#xxx07012 Myhostdir]$ pwd
/home/user/Myhostdir
[user#swathi07012 Myhostdir]$ ls -al
total 12
drwxrwxr-x. 2 user user 38 Jun 2 23:12 .
drwx------. 18 user user 4096 Jun 2 23:11 ..
-rw-rw-r--. 1 user user 15 Jun 2 23:12 text.2.txt
-rw-rw-r--. 1 user user 25 Jun 2 23:12 text.txt
This is partially a Docker issue, but mostly an SELinux issue. I am assuming you are running an old 1.x version of Docker.
You have a couple of options. First, you could take a look at this blog post to understand the issue a bit more and possibly use the fix mentioned there.
Or you could just upgrade to a newer version of Docker. I tested mounting a simple volume on Docker version 18.03.1-ce:
docker run -it --name test -v /home/chris/test:/mydata centos:latest /bin/bash
[root#bfec7af20b99 /]# cd mydata/
[root#bfec7af20b99 mydata]# ls
test.txt.txt
[root#bfec7af20b99 mydata]# ls -l
total 0
-rwxr-xr-x 1 root root 0 Jun 3 00:40 test.txt.txt

Permission denied when get contents generated by a docker container on the local fileystem

I use the following command to run a container:
docker run -it -v /home/:/usr/ ubuntu64 /bin/bash
Then I run a program in the container, the program generates some files in the folder:/usr/ which also appear in /home/ but I can't access the generated files with an error: Permission denied outside the container.
I think this may because the files generated by root in the container but outside the container, the user have no root authority, but how to solve it?
What I want to do is accessing the files generated by the program(installed in the container) outside the container.
You need to use the -u flag
docker run -it -v $PWD:/data -w /data alpine touch nouser.txt
docker run -u `id -u` -it -v $PWD:/data -w /data alpine touch onlyuser.txt
docker run -u `id -u`:`id -g` -it -v $PWD:/data -w /data alpine touch usergroup.txt
Now if you do ls -alh on the host system
$ ls -alh
total 8.0K
drwxrwxr-x 2 vagrant vagrant 4.0K Sep 9 05:22 .
drwxrwxr-x 30 vagrant vagrant 4.0K Sep 9 05:19 ..
-rw-r--r-- 1 root root 0 Sep 9 05:21 nouser.txt
-rw-r--r-- 1 vagrant root 0 Sep 9 05:21 onlyuser.txt
-rw-r--r-- 1 vagrant vagrant 0 Sep 9 05:22 usergroup.txt

Mount "named volume" as non-root in Docker

Is there any way to mount a named volume as a non-root user? I am trying to avoid having to run a chown in each Dockerfile but I need the mount to be writable by a non-root user to be able to write the artifacts created by a build in the image
This is what I'm trying
docker run --rm -it -v /home/bob/dev/:/src/dev -v builds:/mnt/build --name build hilikus/build /bin/bash
but for the second mount I get
[user#42f237282128 ~]$ ll /mnt
total 4
drwxr-xr-x 2 root root 4096 Sep 18 19:29 build
My other mount (/src/dev/) is owned by user, not by root so it gives what I need; however, I haven't been able to do the same with the named volume.
The named volume initializes to the contents of your image at that location, so you need to set the permissions inside your Dockerfile:
$ cat df.vf-uid
FROM busybox
RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
$ docker build -t test-vf -f df.vf-uid .
Sending build context to Docker daemon 23.06 MB
Step 1 : FROM busybox
---> 2b8fd9751c4c
Step 2 : RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
---> Using cache
---> 41390b132940
Successfully built 41390b132940
$ docker run -v test-vol:/data --rm -it test-vf ls -alR /data
/data:
total 12
drwxr-xr-x 2 1000 root 4096 Sep 19 15:26 .
drwxr-xr-x 19 root root 4096 Sep 19 15:26 ..
-rw-r--r-- 1 1000 root 12 Aug 22 11:43 hello
If you use the new --mount syntax instead of the old -v/--volume syntax it is supposedly possible to assign a uid to the volume's contents via docker volume create somename --opt -o=uid=1000 or something similar.
See https://docs.docker.com/engine/reference/commandline/volume_create/#driver-specific-options
I haven't fully tested this to run as non-root or using the dockremap dynamic user with the userns-map option but hope to soon.

How to read and write to mounted volume without running as root?

When mounting a volume with the following command:
docker run -t -i --volumes-from FOO BAR
the volumes from FOO are mounted with root as owner. I can't read and write to that without running as root as far as I know. Must I run as root or is there some other way?
I have tried by creating the folder with other owner before mounting but the mounting seems to overwrite that.
Edit: A chown would work if it could be done automatically after the mounting somehow.
I'm not sure why you aren't able to change your folder permissions in your source image. This works without issue in my lab:
$ cat df.vf-uid
FROM busybox
RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
$ docker build -f df.vf-uid -t test-vf-uid .
...
Successfully built 41390b132940
$ docker create --name test-vf-uid -v /data test-vf-uid
e12df8f84a3b1f113ad5440b62552b40c4fd86f99eec44698af9163a7b960727
$ docker run --volumes-from test-vf-uid -u 1000 -it --rm busybox /bin/sh
/ $ ls -al /data
total 12
drwxr-xr-x 2 1000 root 4096 Aug 22 11:44 .
drwxr-xr-x 19 root root 4096 Aug 22 11:45 ..
-rw-r--r-- 1 1000 root 12 Aug 22 11:43 hello
/ $ echo "success" >/data/world
/ $ ls -al /data
total 16
drwxr-xr-x 2 1000 root 4096 Aug 22 11:46 .
drwxr-xr-x 19 root root 4096 Aug 22 11:45 ..
-rw-r--r-- 1 1000 root 12 Aug 22 11:43 hello
-rw-r--r-- 1 1000 root 8 Aug 22 11:46 world
/ $ cat /data/hello /data/world
hello world
success
/ $ exit
So, what I ended up doing was mounting the volume to another container and change the owner (using uid of the owner I wanted in the final setup) from that container. Apparently uid's are uid's regardless. This means that I can run without being root in the final container. Perhaps there are easier ways to do it but this seems to work at least. Something like this: (untested code clip from my final solution)
docker run -v /opt/app --name Foo ubuntu /bin/bash
docker run --rm --volumes-from Foo -v $(pwd):/FOO ubuntu bash -c "chown -R 9999 /opt/app"
docker run -t -i --volumes-from FOO BAR

Resources