Почему папка, созданная WORKDIR, принадлежит пользователю root вместо пользователя USER? - PullRequest
2 голосов
/ 11 июля 2019

У меня есть следующий Dockerfile

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

Когда я запускаю контейнер и выполняю ls /home/dev, папка Projects принадлежит root.Игнорирует ли WORKDIR тот факт, что USER был вызван ранее?

Ответы [ 2 ]

2 голосов
/ 11 июля 2019

Мне не удалось найти подробные документы для этого, но я заинтересован в этом, поэтому я просто искал исходный код докера , я думаю, мы можем получить подсказку из исходного кода:

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, следующий код:

мобы / демон / workdir.go:

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

Выше мы видим, как это называется SetupWorkingDirectory, следующий код:

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), следующий код:

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.

Наконец, что здесь rootIdentity

Это передается здесь как daemon.idMapping.RootPair(), следующее объявление:

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

См. Описание функции:

RootPair возвращает пару uid и gid для пользователя root

Вы можете продолжить видеть, что такое GetRootUIDGID, но я думаю, что этого достаточно с помощью функции desc. Наконец, будет использоваться изменение владельца WORKDIR на root.

И дополнительно посмотреть, что USER делает?

__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.

И, если вы хотите сменить владельца, я думаю, вам придется сделать это самостоятельно, используя chown либо RUN, либо ENTRYPOINT/CMD.

0 голосов
/ 11 июля 2019

Docker всегда запускается от имени пользователя root в своей среде, поэтому вместо этого мы указываем использовать другого пользователя.

Поэтому, прежде чем что-либо запускать, мы можем добавить пользователя в его среду, а затем указать, что useR для выполнения действий в Dockerfile.

Этот пример добавления пользователя в 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 &&\
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...