Docker on MacOSX does not translate file ownership

2019-02-09 05:51发布

I use a simple Linux machine in Docker. Using it with Linux, I clone my dev repository and mount the repo as a volume in Docker. Then, when I enter into the Docker container, the files in the volume belong to user 1000 in group 1000 (all is fine because Docker keeps correctly all file owners). Now I'm trying to do the same in macOS, but in my macOS machine, my uid is 501 and my gid is 20. But when I go to the container, I realize that files inside it have gid and uid 0, the same as root. What can I do to keep file ownership in Docker?

标签: macos docker
2条回答
祖国的老花朵
2楼-- · 2019-02-09 06:18

TL;DR

The osxfs driver pretends that the files are owned by the USER that the container runs as. If you are seeing mounted files as being owned by root, your container probably is set to run as root.


The longer version

The osxfs driver on macOS tells a bit of a lie about ownership. Here is the relevant section of the documentation (emphasis mine):

Ownership

Initially, any containerized process that requests ownership metadata of an object is told that its uid and gid own the object. When any containerized process changes the ownership of a shared file system object, e.g. with chown, the new ownership information is persisted in the com.docker.owner extended attribute of the object. Subsequent requests for ownership metadata will return the previously set values. Ownership-based permissions are only enforced at the OS X file system level with all accessing processes behaving as the user running Docker. If the user does not have permission to read extended attributes on an object (such as when that object’s permissions are 0000), osxfs will attempt to add an access control list (ACL) entry that allows the user to read and write extended attributes. If this attempt fails, the object will appear to be owned by the process accessing it until the extended attribute is readable again.

In other words,

  1. Inside the container, the osxfs driver pretends that whatever uid/gid is running in the container is also the uid/gid that owns the mounted files.

  2. If you chown files (in the container) to something else, no chown is performed on the real files; this owner information is stored in an extended file attribute instead, and that value is used by the container (and ignored by macOS).

  3. The real files are owned by whoever owns them in macOS, outside the container. Access control is determined using those real file ownerships, and the uid/gid of the user running the Docker applications (which is probably your login user on the Mac).

I'll use a container on my Mac as an example. I built this container, and here is part of its Dockerfile:

FROM ubuntu:16.04
RUN useradd -d /planner -m planner
WORKDIR /planner
USER planner

As you can see, this container runs as the user "planner". As is typical in Ubuntu, being the first user added to this new system, it has a uid of 1000 and a gid of 1000.

Outside, on my Mac, my uid and gid are also typical (501, 20), but not the same as the "planner" user in my container.

I run this container with an external directory mounted, which contains my code. That's so I can reload the application during development without rebuilding the container (a common use case).

version: '2'
services:
  uwsgi:
    image: planner:latest
    build: ./uwsgi
    volumes:
      - ./uwsgi/planner:/planner

If I look at the source directory (./uwsgi/planner) on my Mac, the files are owned by me (uid 501, gid 20).

-rw-r--r--   1 dan  staff  3103 Oct 24 23:28 README.md
drwxr-xr-x   4 dan  staff   136 Sep 14  2016 doc
-rwxr-xr-x   1 dan  staff   260 Sep 14  2016 manage.py
drwxr-xr-x   7 dan  staff   238 Jan 11 00:00 site_planner
drwxr-xr-x   4 dan  staff   136 Jan 10 19:07 node_modules
drwxr-xr-x  12 dan  staff   408 Mar 30 12:30 planner
-rw-r--r--   1 dan  staff   112 Oct  5 10:28 requirements.txt

But looking at the mounted directory inside the container, you can see that while the paths, dates, and sizes are the same, osxfs has masked the owner and told the container OS that these files are actually owned by "planner". The actual name and uid of the user are not important here. The osxfs driver is just using whatever the current user is. If you have a user with uid 1005 named "joe", then that is what you'll see instead.

-rw-r--r--  1 planner planner 3103 Oct 25 03:28 README.md
drwxr-xr-x  4 planner planner  136 Sep 14  2016 doc
-rwxr-xr-x  1 planner planner  260 Sep 14  2016 manage.py
drwxr-xr-x  7 planner planner  238 Jan 11 05:00 site_planner
drwxr-xr-x  4 planner planner  136 Jan 11 00:07 node_modules
drwxr-xr-x 12 planner planner  408 Mar 30 16:30 planner
-rw-r--r--  1 planner planner  112 Oct  5 14:28 requirements.txt

Now, this is just the osxfs driver on Mac. And it is done in the name of simplicity - on a Mac you are probably doing development work, and the nuances of file permissions are just a pain you have to work around. Also, notice that you are not able to execute this kind of chown on your Mac without using sudo or another tool to elevate your privileges.

$ chown 1000 manage.py
chown: manage.py: Operation not permitted

This matters, because aside from vmnetd, all of the Docker processes running on your Mac run as you, not as root. (That includes the osxfs process, as you can see in this screenshot.)

Activity Monitoring showing Docker processes

On a Linux server, it works more like you expect it to work. For example, as part of the same service I used in my example, I have a postgres container, and it uses an external directory for its data store. On my Mac, that directory is full of files owned by me (but the container thinks they are owned by user "postgres"). But, on the server, the real uids are preserved on the external filesystem.

$ ls -ln pgdata
total 120
drwx------. 6 999 999  4096 Oct 31 21:06 base
drwx------. 2 999 999  4096 Mar  8 19:22 global
drwx------. 2 999 999  4096 Oct 31 21:06 pg_clog
drwx------. 2 999 999  4096 Oct 31 21:06 pg_commit_ts
drwx------. 2 999 999  4096 Oct 31 21:06 pg_dynshmem
drwx------. 4 999 999  4096 Oct 31 21:06 pg_logical
drwx------. 4 999 999  4096 Oct 31 21:06 pg_multixact
drwx------. 2 999 999  4096 Mar  8 19:22 pg_notify
drwx------. 2 999 999  4096 Oct 31 21:06 pg_replslot
drwx------. 2 999 999  4096 Oct 31 21:06 pg_serial
drwx------. 2 999 999  4096 Oct 31 21:06 pg_snapshots
drwx------. 2 999 999  4096 Mar  8 19:22 pg_stat
drwx------. 2 999 999  4096 Apr  4 17:08 pg_stat_tmp
drwx------. 2 999 999  4096 Mar 20 15:36 pg_subtrans
drwx------. 2 999 999  4096 Oct 31 21:06 pg_tblspc
drwx------. 2 999 999  4096 Oct 31 21:06 pg_twophase
drwx------. 3 999 999  4096 Mar 17 18:30 pg_xlog
-rw-------. 1 999 999     4 Oct 31 21:06 PG_VERSION
-rw-------. 1 999 999  4496 Oct 31 21:06 pg_hba.conf
-rw-------. 1 999 999  1636 Oct 31 21:06 pg_ident.conf
-rw-------. 1 999 999    88 Oct 31 21:06 postgresql.auto.conf
-rw-------. 1 999 999 22233 Oct 31 21:06 postgresql.conf
-rw-------. 1 999 999    37 Mar  8 19:22 postmaster.opts
-rw-------. 1 999 999    68 Mar  8 19:22 postmaster.pid

Here the files are owned by uid 999, gid 999. That is not my uid (which is 5046 on this particular server).

999 is the uid of postgres inside the container, and that is exposed externally in the file permissions here.

In other words, the issue you are having is Mac-specific, and you should not have the same issue using Linux in production.

查看更多
Deceive 欺骗
3楼-- · 2019-02-09 06:19

What can I do to keep file ownership in docker?

why do you need to do this?

if you're using a host-mounted volume (via docker run, with -v $PWD:/my/app args for example) in your container, then it doesn't matter what the permissions are in the image itself.

you can edit the files on your mac and the changes will be immediately reflected in the container.

this is all i ever do from my mac, and i never have issues editing files in my volume or having those changes reflected in the container

查看更多
登录 后发表回答