本文介绍了为什么由WORKDIR创建的文件夹由root而不是USER拥有的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下Dockerfile

I have the following Dockerfile

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

当我启动一个容器并执行 ls/home/dev 时, Projects 文件夹归 root 所拥有.WORKDIR是否忽略USER被更早调用的事实?

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?

推荐答案

我没有为此找到详细的文档,但是对此我很感兴趣,所以我只看了 docker源代码,我想我们可以从源代码中获得线索:

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(第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)
}

上面,我们可以看到它将调用 ContainerCreateWorkdir ,接下来是代码:

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())
}

上面,我们可以看到它叫做 SetupWorkingDirectory ,接下来是代码:

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

moby/container/container.go(第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
}

上面,我们可以看到它叫做 MkdirAllAndChownNew(pth,0755,rootIdentity),接下来是代码:

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

moby/pkg/idtools/idtools.go(第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)
}

以上将在中间构建容器&中设置文件夹还可以使用 rootIdentity 更改文件夹的所有权.

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

最后,这里的 rootIdentity 是什么?

它通过 daemon.idMapping.RootPair()传递到这里,接下来是声明:

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

moby/pkg/idtools/idtools.go(第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}
}

请参见函数desc:

您可以继续查看 GetRootUIDGID 是什么,但我认为现在从函数desc中就足够了.最终它将使用将 WORKDIR 的所有权更改为 root 的所有权.

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.

此外,还可以看到 USER 做什么?

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))
}

上面,仅将用户设置为运行config并直接提交进一步的命令,但与 WORKDIR 设置无关.

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

而且,如果您想更改所有权,我想您将必须自己使用 chown RUN ENTRYPOINT/CMD .

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.

这篇关于为什么由WORKDIR创建的文件夹由root而不是USER拥有的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 20:03