Open kbrwn opened 7 years ago
Is this related to https://github.com/docker/docker/issues/11462 ?
Closer to (closed but not actually solved): https://github.com/docker/docker/issues/6880
@thaJeztah this problem affects most versions of docker (latest included). The chmod
workaround in https://github.com/docker/docker/issues/31106 has regressed in 1.12+, so now this is blocking a path forward for my team(s)
@crosbymichael @mlaventure any more information I can provide? happy to work through this together
Still having this problem on 17.0.5 I have to do this instead
I just noticed that this is normally how linux operates. (Running on host, no docker at all)
user1@turing ~ $ sudo su - user2
user2@turing ~ $ ls > /dev/stderr
-su: /dev/stderr: Permission denied
user2@turing ~ $ ls /dev/pts/16 -la
crw------- 1 user1 tty 136, 16 May 30 17:11 /dev/pts/16
So... do we want to close this and say "Well that's just how Linux works?" or try and overcome this, so that docker is more useable/user friendly?
docker run -it --rm debian:8 bash -c "useradd test; su - test"
No directory, logging in with HOME=/
$ ls > /dev/stderr
-su: 1: cannot create /dev/stderr: Permission denied
$ bash -c "ls > /dev/stderr"
bash: /dev/stderr: Permission denied
$ bash
test@9390f87104a5:/$ ls > /dev/stderr
bash: /dev/stderr: Permission denied
test@9390f87104a5:/$ ls /proc/$$/fd -la
total 0
dr-x------ 2 test test 0 May 30 20:51 .
dr-xr-xr-x 9 test test 0 May 30 20:51 ..
lrwx------ 1 test test 64 May 30 20:51 0 -> /13
lrwx------ 1 test test 64 May 30 20:51 1 -> /13
lrwx------ 1 test test 64 May 30 20:51 2 -> /13
lrwx------ 1 test test 64 May 30 20:51 255 -> /13
But this does work
docker exec -it 9390f87104a5 bash
test@9390f87104a5 :/$ ls > /dev/stderr
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
More info
docker exec -it 9390f87104a5 ls /proc/1/fd -la
total 0
dr-x------ 2 root root 0 May 30 20:57 .
dr-xr-xr-x 9 root root 0 May 30 20:57 ..
lrwx------ 1 root root 64 May 30 20:57 0 -> /13
lrwx------ 1 root root 64 May 30 20:57 1 -> /13
lrwx------ 1 root root 64 May 30 20:57 2 -> /13
lrwx------ 1 root root 64 May 30 21:01 255 -> /13
But this does work
docker run -it --rm --user games debian:8 bash -c "ls > /dev/stderr"
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
docker run -it --rm --user games debian:8 bash
games@34d7f39fa933:/$ ls /proc/1/fd -la
total 0
dr-x------ 2 games games 0 May 30 20:54 .
dr-xr-xr-x 9 games games 0 May 30 20:54 ..
lrwx------ 1 games games 64 May 30 20:54 0 -> /13
lrwx------ 1 games games 64 May 30 20:54 1 -> /13
lrwx------ 1 games games 64 May 30 20:54 2 -> /13
lrwx------ 1 games games 64 May 30 20:54 255 -> /13
The current workaround I still have to use is:
docker run -it --rm debian:8
root@eecfdfdd7ed5:/# useradd test
root@eecfdfdd7ed5:/# su - test
test@eecfdfdd7ed5:/tmp$ cd /tmp
test@eecfdfdd7ed5:/tmp$ touch 1
test@eecfdfdd7ed5:/tmp$ touch 12
test@eecfdfdd7ed5:/tmp$ touch 3
test@eecfdfdd7ed5:/tmp$ (ls > >(cat 1>&2)) 2> /dev/null # As you can see, no output. It's working!
test@eecfdfdd7ed5:/tmp$ (ls > >(cat 1>&2)) 1> /dev/null
test@eecfdfdd7ed5:/tmp$ 1
12
3
blah.txt
thanks @andyneff - I'll give it a shot
I also hit this today. I am circumventing by doing a one-time
sudo chmod o+w /dev/stdout
from the user account. Any news on an official fix?
Thanks @andre-richter ! Do You know why this actually works? I do not see any difference in permissions after running this chmod...
I'm using this chmod o+w /dev/stdout
thing as last line before exec in my custom docker-entrypoint.sh
:
# beign able to write to /dev/stdout not only by root user
# https://github.com/moby/moby/issues/31243
chmod o+w /dev/stdout
exec sudo -Eu www-data "$@" >/dev/stdout 2>/dev/stdout
@lechup, you are probably looking at /dev/stdout
when you say the permissions didn't change. But /dev/stdout
points to /proc/self/fd/1
which usually points to /dev/pts/0
or similar, and that's what you are changing permissions on.
Normally in linux, only root:tty
can write directly to this.
Edit: When running a container without TTY, /proc/self/fd/0,1,2
is a pipe, with root:root
permissions by default.
@andyneff great tip ... an effective workaround to this issue is to elevate the non-root user to be in the tty
group: better than running as root
.
useradd -G tty test
Edit: Note that for this to work, you must allocate a TTY, i.e. -t
or compose tty: true
.
Just to rehash, there three solutions to this problem
chmod
/chown
/dev/std*
so that your non-root user has permission.
docker exec -t
, the new pts will need to be fixed too. So that's one downside to this solution.Add the tty
group permissions to the user like @javabrett suggested. This is a more permanent solution, as additional docker exec -t
will work.
usermod -a -G tty test
A third idea involves the source of the tty permission. The group permission of pts' are controlled by the /dev/pts
mount
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
/dev/shm
have customizable behavior here--pts-gid
flag or --pts-mode
or similar, then there would be a third solution tty
perimissionSo it looks like currently, 2 is the best work around
/dev/pts
, /proc/self/fd
0-2 are pipes that you can't chmod or chown, and have no group permissions allowed. Again, this is how linux works, and is not technically a docker bug.The comments in this thread focus on accessing /dev/stdout
from a shell inside the container, but I've noticed it happens outside as well.
Super standard vaultwarden that uses sqlite:
version: "3.7"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
volumes:
- ./vaultwarden-data:/data
Now from my shell not in a container I can see the files here:
nat@natbox ~> docker-compose --file vaultwarden.docker-compose.yml up -d
nat@natbox ~> ll ~/vaultwarden*
-rw-r--r-- 1 nat nat 415 Nov 12 01:58 vaultwarden.docker-compose.yml
drwxr-xr-x 3 nat nat 4.0K Nov 17 20:22 vaultwarden-data/ # CONTAINER VOLUME MOUNT POINT
-rw-r--r-- 1 root root 172K Nov 12 01:58 vaultwarden-data/db.sqlite3 # INSIDE CONTAINER
-rw-r--r-- 1 root root 32K Nov 17 20:49 vaultwarden-data/db.sqlite3-shm
-rw-r--r-- 1 root root 0 Nov 17 20:22 vaultwarden-data/db.sqlite3-wal
Ok let's take a SQLite backup:
nat@natbox ~> sqlite3 ./vaultwarden-data/db.sqlite3 ".backup /dev/stdout" | restic backup --stdin --stdin-filename vault.sqlite3
Error: cannot open "/dev/stdout"
...
error: read /vault.sqlite3: no data read
Fatal: unable to save snapshot: snapshot is empty
So... I'm trying to wrap my head around this... sqlite3
is a process running on the host, as user nat
, writing to /dev/stdout
, and this fails? This is not running in a container (although the database is also being used by a Rust process in Vaultwarden)
For reasons I don't understand, sudo
doesn't help.
@heyheyhello Unfortunately your sqlite3 issue is unrelated. I don't think you use .backup
that way, despite the error appearing to be a permission issue, it is not. It's an sqlite3 issue.
As a workaround, use redirections and don't use the /dev/stdout
file name. It's possible to use output redirections to run a script under a non-privileged account and redirect output to Docker logs:
$ su user -c "command" > /proc/1/fd/1 2>&1 # run command as a non-privileged user and wait for it, redirecting its output to Docker
In this example, the command's /proc/self/fd/1,2 will be accessible to open and write, so the standard outputs will be redirected to Docker logs.
To be able to run child processes in the background as non-privileged users and still log to Docker logs:
Add custom file descriptors to the intermediary script:
$ su user -c "command" > /proc/1/fd/1 2>/proc/1/fd/2 3>&1 4>&2 # run the command as a non-privileged user with custom file descriptors and wait for it. Redirect the output of the command to Docker. Redirect custom file descriptors to Docker as well.
Spawn background processes in the command
script:
$ sub-command >&3 2>&4 & # run background process as a non-privileged user, not wait for it, redirect its output to custom file descriptors and thus to Docker.
In this example, the "command" will spawn "sub-command" in the background which will not require any further modifications or redirections. All its standard outputs will be redirected to the custom descriptors 3 and 4 and then to Docker logs even if the parent process exited.
You may run all of this from a tty console from under the root user as well. The only limitation is that you must run everything as the root user when using docker exec
and go through su
s and redirections when you need to run anything as a non-privileged user and store its output in Docker logs.
For tty consoles, running su
in this way:
su test > /proc/1/fd/1 2>&1
will lead to outputting everything to Docker logs and to the console simultaneously. Very similar to the subject's expected result but without using the /dev/stdout
name.
I've come to this solution and it works for me for now. My task was in redirecting background non-privileged processes' output to Docker logs while the Docker entrypoint is required to be executed under the root user. While it adds workarounds, they're simple and don't require additional tools installation or fine-tuning/customizing of Docker or Linux.
a work around I found is the following:
yq -P '.' your_file.json -oy | grep '' > your_file.yaml
Description
Permission error received when attempting to write to
/dev/stdout
as a non-root user:Steps to reproduce the issue:
Describe the results you received:
A permissions error is received despite the permissions being
lrwxrwxrwx
:Describe the results you expected:
echo command to /dev/stdout completes without permissions error.
Additional information you deem important (e.g. issue happens only occasionally):
Output of
docker version
:Output of
docker info
:Additional environment details (AWS, VirtualBox, physical, etc.):
Same result on virutualbox/vagrant (Fedora 25) and Container Linux 1325.0.0 (docker 1.13.1) Previously (1.10 and 1.11) this could be worked around by chmoding /dev/stdout.