Why is a folder created by WORKDIR owned by root instead of USER

五迷三道 提交于 2021-02-19 03:59:48

问题


I have the following Dockerfile

ARG DEV_USER=dev
# Other stuff ...
USER $DEV_USER
# Other stuff ...
WORKDIR /home/$DEV_USER/Projects

When I start a container and execute ls /home/dev, the Projects folder is owned by root. Does WORKDIR ignore the fact that USER was invoked earlier?


回答1:


I failed to find detail documents for this, but I'm interested on this, so I just had a look for docker source code, I guess we can get the clue from sourcecode:

moby/builder/dockerfile/dispatcher.go (Line 299):

// Set the working directory for future RUN/CMD/etc statements.
//
func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
    ......
    if err := d.builder.docker.ContainerCreateWorkdir(containerID); err != nil {
        return err
    }

    return d.builder.commitContainer(d.state, containerID, runConfigWithCommentCmd)
}

Above, we can see it will call ContainerCreateWorkdir, next is the code:

moby/daemon/workdir.go:

func (daemon *Daemon) ContainerCreateWorkdir(cID string) error {
    ......
    return container.SetupWorkingDirectory(daemon.idMapping.RootPair())
}

Above, we can see it call SetupWorkingDirectory, next is the code:

moby/container/container.go (Line 259):

func (container *Container) SetupWorkingDirectory(rootIdentity idtools.Identity) error {
    ......
    if err := idtools.MkdirAllAndChownNew(pth, 0755, rootIdentity); err != nil {
        pthInfo, err2 := os.Stat(pth)
        if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
            return errors.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
        }

        return err
    }

    return nil
}

Above, we can see it call MkdirAllAndChownNew(pth, 0755, rootIdentity), next is the code:

moby/pkg/idtools/idtools.go (Line 54):

// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
// ownership ONLY of newly created directories to the requested uid/gid. If the
// directories along the path exist, no change of ownership will be performed
func MkdirAllAndChownNew(path string, mode os.FileMode, owner Identity) error {
    return mkdirAs(path, mode, owner, true, false)
}

Above will setup folder in intermediate build container & also change the ownership of the folder with rootIdentity.

Finally, what is rootIdentity here?

It's passed here as daemon.idMapping.RootPair(), next is the declare:

moby/pkg/idtools/idtools.go (Line 151):

// RootPair returns a uid and gid pair for the root user. The error is ignored
// because a root user always exists, and the defaults are correct when the uid
// and gid maps are empty.
func (i *IdentityMapping) RootPair() Identity {
    uid, gid, _ := GetRootUIDGID(i.uids, i.gids)
    return Identity{UID: uid, GID: gid}
}

See the function desc:

RootPair returns a uid and gid pair for the root user

You can continue to see what GetRootUIDGID is, but I think it's enough now from the function desc. It will finally use change the ownership of WORKDIR to root.

And, additional to see what USER do?

__moby/builder/dockerfile/dispatcher.go (Line 543):__

// USER foo
//
// Set the user to 'foo' for future commands and when running the
// ENTRYPOINT/CMD at container run time.
//
func dispatchUser(d dispatchRequest, c *instructions.UserCommand) error {
    d.state.runConfig.User = c.User
    return d.builder.commit(d.state, fmt.Sprintf("USER %v", c.User))
}

Above, just set user to run config and directly commit for further command, but did nothing related to WORKDIR setup.

And, if you want to change the ownership, I guess you will have to do it by yourself use chown either in RUN or ENTRYPOINT/CMD.




回答2:


Docker is always run as root user in its environment, SO instead we specify it to use another user.

So before running anything we can add a user to its environment then specify that useR to perform action in Dockerfile.

This example add user to www-data

ARG USER_ID=1000
ARG GROUP_ID=1000

RUN groupadd -g ${GROUP_ID} www-data &&\
    useradd -l -u ${USER_ID} -g www-data www-data &&\


来源:https://stackoverflow.com/questions/56980608/why-is-a-folder-created-by-workdir-owned-by-root-instead-of-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!