Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make write access work by default on Linux #11

Closed
WMDE-Fisch opened this issue Oct 2, 2019 · 11 comments
Closed

Make write access work by default on Linux #11

WMDE-Fisch opened this issue Oct 2, 2019 · 11 comments

Comments

@WMDE-Fisch
Copy link

When using fresh under Linux with npm install you mostly get write access errors. It might be nice to add a hint about the rights needed to the readme.

In that case it's also a bit misleading, that the script says something like /mediawiki (read-write) although the directory is not writable.

@kostajh kostajh changed the title Add hint for wirte access Add hint for write access Oct 2, 2019
@Krinkle
Copy link
Member

Krinkle commented Oct 2, 2019

It not being writable would be a bug. Definitely not something that should be documented, but rather fixed. The 99% use case of fresh-node as I use it every day is to run npm install && npm test. It creates and writes to the node_modules directory locally without issue for me.

Can you paste the Docker distro/version, Linux distro/version, Fresh version, parameters to fresh-node, and the permissions of the MW directory?

@Krinkle Krinkle added the support label Oct 4, 2019
@WMDE-Fisch
Copy link
Author

I've got Ubuntu 18.04 with 4.15.0-43-generic

docker version

Client:
 Version:           18.09.7
 API version:       1.39
 Go version:        go1.10.1
 Git commit:        2d0083d
 Built:             Fri Aug 16 14:20:06 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.09.7
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.1
  Git commit:       2d0083d
  Built:            Wed Aug 14 19:41:23 2019
  OS/Arch:          linux/amd64
  Experimental:     false

fresh-node

# fresh: 19.10.1 (2019-10-01)
# image: docker-registry.wikimedia.org/releng/node10-test-browser:0.6.0-s1
# software: Debian Linux 9 Stretch
#           Node.js v10.15.2 (npm 6.5.0)
#           Chromium 71.0.3578.80
#           Mozilla Firefox 60.8.0
#           JSDuck 5.3.4 (Ruby 2.3.3)
# mount: /mediawiki      ➟ /var/www/mediawiki      (read-write)
#        /mediawiki/.git ➟ /var/www/mediawiki/.git (read-only)

from my machine

drwxr-xr-x 18 chfi chfi 4096 Okt  7 15:18 mediawiki/

from fresh

drwxr-xr-x  18 1001 1001 4096 Oct  7 13:18 mediawiki

But still I get this when I run npm install

npm WARN checkPermissions Missing write access to /mediawiki
npm ERR! path /mediawiki
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/mediawiki'
npm ERR!  { [Error: EACCES: permission denied, access '/mediawiki']
npm ERR!   stack: 'Error: EACCES: permission denied, access \'/mediawiki\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/mediawiki' }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).

npm ERR! A complete log of this run can be found in:
npm ERR!     /cache/_logs/2019-10-07T13_24_37_056Z-debug.log

@Krinkle
Copy link
Member

Krinkle commented Oct 7, 2019

Can you check your Docker agent configuration? Maybe there is something there that is limiting the daemon from writing to this directory. I cannot reproduce this on macOS.

@tarrow
Copy link

tarrow commented Dec 16, 2019

I also have this problem but not enough time to dig into it right now.

As far as I know the issue is that fresh is actually running (normally) as UID 65534. In my case this is also nobody on the machine running docker. This unsurprisingly doesn't have permission to source files owned by my user.

What we have done in the past is things like this: https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/Wikibase/+/master/client/data-bridge/Dockerfile

e.g. building images that use to correct permissions as the developer user account.

It looks like with some cursory googling but almost 0 OSx knowledge on my part that the mac docker agent does some special permission faking to make it appear that the container process has ownership even if normally it wouldn't. See https://docs.docker.com/docker-for-mac/osxfs/#ownership

I think on Linux nothing special is done like this at all so given the container if running as nobody it has the same permissions as nobody on the host (i.e. not enough to write to my user dir)

@Krinkle
Copy link
Member

Krinkle commented Jan 7, 2020

Thanks, I also found https://denibertovic.com/posts/handling-permissions-with-docker-volumes/ based on this.

It looks to me like Docker is effectively broken on Linux then. I realise now the internals of why this is hard and difficult, but the use case of being able to mount a directory and have it be read-write seems rather important and should be able to work out of the box with nothing more than run-time flag to --mount. A flag that solves "given user X on the outside, and user Y on the inside, set up the necessary bits to allow the container to write as user X through the docker layers", without the Docker image having to know about the specific user X's uid ahead of time (as the images have to be public and re-usable), and without requiring root access on the host. The directory is writable by the current user and I'm running Docker as that same user, that shouldn't require more access.

I'm open to other suggestions for how to get this working :)

@Krinkle Krinkle added bug and removed support labels Jan 7, 2020
@Krinkle Krinkle changed the title Add hint for write access Make write access work by default on Linux Jan 7, 2020
@Krinkle
Copy link
Member

Krinkle commented Jan 22, 2020

On an upstream issue (moby/moby#2259) I noticed the following comment:

Podman is a rootless Docker drop-in replacement … https://podman.io/. With podman, root is not used so user permission is handled correctly. Our team switched to Podman due to this problem and worked very well.

This may be worth trying out. Not just for fixing read-write on Linux, but also more generally to avoid needing root (ref #4).

@kostajh
Copy link
Contributor

kostajh commented Jan 27, 2020

I can confirm that podman works, but the script needs some modification:

  • add --userns=keep-id to preserve the user ID
  • change --mount type to --mount=type
    • instead of target, you use destination
    • the readonly flag doesn't work (for the git dir) -- there is probably some equivalent I just didn't look it up yet.
    • drop the consistency flags

So the final command looks something like:

podman run --userns=keep-id --rm --interactive --tty -e 'HOME=/tmp' \
	--mount=type=bind,source="$mountsrc",destination="$mountdest" \
	$( if [ -n "$bind_git_ro" ]; then printf %s "--mount=type=bind,source="$mountsrc"/.git,target="$mountdest"/.git,readonly"; fi ) \
	${docker_args[@]+"${docker_args[@]}"} \
	--entrypoint /bin/sh \
	"$imagename:$imageversion" \
	-c "cd $mountdest/;$welcomecmd;bash"

@niedzielski
Copy link

I had this same issue on Ubuntu v19.10. I added -u "$(id -u "$USER"):$(id -g "$USER")" to the docker run command which seems to work. I'm not sure what the security implications are but maybe it's ok as I don't mount /etc/passwd and /etc/group.

kostajh added a commit to kostajh/fresh that referenced this issue Apr 2, 2020
@niedzielski
Copy link

-u "$(id -u "$USER"):$(id -g "$USER")"

While trying to play video games, I came across this similar approach which seems to suggest the idea works for some:

add_run_args_for_as_me () {
    USER_HOME="${HOME}"
    WORKDIR="${USER_HOME}"
    add_run_arg --env="USER_NAME=$(whoami)"
    add_run_arg --env="USER_UID=$(id -u)"
    add_run_arg --env="USER_GID=$(id -g)"
    add_run_arg --env="USER_HOME=${USER_HOME}"
}

These variables appear to feed into the entrypoint which otherwise defaults to presumably sensible values.

There are likely some Windows eccentricities in the script but I thought the structure of it looked nice and it might overall be a good reference to consider. I'm sure there's other Docker wrappers out that solve similar problems too but happened upon this one.

@Krinkle
Copy link
Member

Krinkle commented Apr 4, 2020

I added -u "$(id -u "$USER"):$(id -g "$USER")" to the docker run command which seems to work.

I found similar ideas in the upstream issue at moby/moby#2259. However, I got the impression that was frowned upon by some more seasoned Linux users because these user IDs would not actually exist within the container. It's interesting that Linux apparently allows mounting directories in a way that has foreign/unregistered user IDs associated with some if its files, and even allows a shell to be opened acting as a user ID that doesn't exist.

The down side, as I gather from various comments at moby/moby#2259, is that various programs don't work if you invoke docker-run this way due to there being no username available, no home shell or home directory etc.

The workaround mentioned there in various different forms (incl. a stackoverflow answer) is to call useradd inside the container (either ahead of time in Dockerfile, or in our case at run-time) and with some kind of username, home directory, home shell, user group, etc. and then associate that with the user ID.

But, maybe we're lucky to not yet have needed any program or npm package that fails under these conditions. I certainly don't mind giving it a try!

@niedzielski
Copy link

The workaround mentioned there in various different forms (incl. a stackoverflow answer is to call useradd inside the container

Seems to have made it into docker-wine's entrypoint too.

moby/moby#2259

I can corroborate NFS id / group mapping difficulties irrespective of Docker!

@Krinkle Krinkle closed this as completed in 95c88d3 Apr 8, 2020
wmfgerrit pushed a commit that referenced this issue May 14, 2020
This allows write access to work on Linux hosts. See
#11 for discussion.

h/t to @niedzielski for the suggestion.

Change-Id: I836534f71d55985d5720b7d8e1e708c7f93ebd45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

5 participants