LINUX.ORG.RU
ФорумAdmin

владелец volume тома в docker

 , , ,


0

2

Всем привет. Сразу к делу.

Как, канонично, выставлять владельца Volume томов при запуске контейнера от non-root пользователя?

Пример: Dockerfile

...
VOLUME [/app/config]

RUN useradd -m -s /bin/nologin abc && \
         chown -R abc:abc /app/config 

USER abc
...
Это классический вариант, постоянно попадается на докер хабе. На хосте создаётся volume c UID:GID владельца равными uid:gid пользователя abc КОНТЕЙНЕРА.
docker run --name debian_test -v /create_vol debian:jessie

Контейнер

chown 10000:10000 /create_vol
drwxr-xr-x   2 10000 10000 4096 Aug  6 15:43 create_vol

Хост

drwxr-xr-x 2 10000 10000 4096 Aug  6 11:43 _data
root@deb-vm-2-template:/var/lib/docker/volumes/52c70dea01d73e435bdfdcc38d2e616bb0e4cd03490ad57d624abeb5e48dff3c#

А это результат пересечения именования.

drwxr-xr-x 2 ssh backup 4096 Aug  6 11:43 _data

Как назначить владельца для созданного тома? Скажем, создаю директорию под конфиг и кидаю туда файлы. Создаю контейнер и маплю ему заранее подготовленный том. В итоге, как видно из примера, проблема с владельцами из-за разного пространства имен.

Пока вижу 2 решения:

  • 1.В скрипте явно указывать юид и создавать пользователя с этим юидом на хосте. Минусы: Каждый раз пилить свой докер скрипт, возможно пересечение имен(т.е. не переносимость скрипта)
  • 2. Создать энтрипоинт скрипт меняющий юид пользователя на юид владельца тома. Подсмотрел у офф репы redis. Минус: костыль

А может быть вообще не в том направлении иду, и нужно по другому разрешения устанавливать.


Я за вас рад

anc ★★★★★ ()

the owner of volum that in docker

KRoN73 ★★★★★ ()

Не успел оформить, а уже столько комментов по теме.)

dzirtt ()

Да, в линуксе uid mapping это боль. Можно заюзать nss extrausers на хосте и контейнере для согласования.

Bers666 ★★★★★ ()

chown -R abc:abc /app/config
Это классический вариант, постоянно попадается на докер хабе.

Бесит ужасно. Скажем, нужно мне в образе redmine показывать репозитории. Монтирую внешний репозиторий. Запускаю контейнер. Бац — файлы хоста принадлежат левоюзеру... Я чуть не застрелился, пока нашёл — репозиторий монтируется ещё в штук 5 LXC-контейнеров, так я на них грешил :) Пришлось для redmine делать отдельную копию и настраивать синк по cron'у...

KRoN73 ★★★★★ ()

У меня 2 варианта использования:

1. Внутри entrypoint создаю пользователя, делаю chown на нужные volume. Минус такого решения - нужно писать хотя бы минимальный entrypoint; из хостовой системы к таким volume может получить доступ либо рут, либо другой пользователя с теми же uid:gid, что создался в докере.

2. На хостовой системы создаю пользователя, из-под которого запускаю конкретный контейнер. Затем либо в Dockerfile, либо в entrypoint создаю пользователя с тем же uid:gid, что и на хостовой системе. Из минусов - нужно либо в Dockerfile менять каждый раз этот uid:gid (сейчас стало проще, можно при build передавать как опцию --build-arg=UID=$(id -u) ); не очень удобно отдельно создавать пользователей под разные типа контейнеров (опять же, в случае с обычными демонами это считается нормально, так что не вижу ничего плохого).

pod ★★ ()

enrypoint

#!/bin/bash

#docker entrypint script
#for sync uid:gid host<->container

#usage
#add to build script ENV USER, ENV GROUP point to user from who start app in container
#docker run -e "HOSTUID=`id -u USERNAME`" -e "HOSTGID=`id -g GROUP`" where user and group its host user:group

set -e
changeFlag=0

# allow the container to be started with `--user`
if [ "$(id -u)" = '0' ]; then
	
    #change container  UID:GID to HOST UID:GID
    #to save right permissions
    
    test -z $HOSTUID && { echo -e "set HOSTUID ENV var, script not work properly \nEXIT"; exit 1; }
    test -z $HOSTGID && { echo -e "set HOSTGID ENV var, script not work properly \nEXIT"; exit 1; }
    id -u $USER &> /dev/null || { echo -e "user $USER not exist in container, script not work properly \nEXIT"; exit 1; }
    id -g $GROUP &> /dev/null || { echo -e "group $GROUP not exist in container, script not work properly \nEXIT"; exit 1; }
   
    if [ $HOSTUID -ne `id -u $USER` ]; then
        usermod -o -u $HOSTUID $USER
        echo -e "set $USER -uid-> $HOSTUID"
        changeFlag=$((changeFlag+1))
    fi
    
    if [ $HOSTGID -ne `id -g $GROUP` ]; then
        groupmod -o -g $HOSTGID $GROUP
        echo -e "set $GROUP -gid-> $HOSTGID"
        changeFlag=$((changeFlag+1))
    fi

    test $changeFlag -eq 0 && echo -e "nothing to be done \n$USER=`id -u $USER` $GROUP=`id -g $GROUP`"

    exec gosu $USER "$0" "$@"
    exit 0
fi

exec "$0" "$@"
exit 0

Dockerfile

#set here user:group from what run service inside container
ENV USER i2psvc
ENV GROUP i2psvc

docker run

-e "HOSTUID=`id -u i2psvc`" -e "HOSTGID=`id -g i2psvc`"

Решил так. Плюсы

  • Скрипт универсальный, не требует изменение от контейнера к контейнеру.

Минусы

  • Для каждого образа делать свой скрипт сборки.
  • Дополнительные параметры при создании контейнера
  • Костыль
dzirtt ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.