Moby: Сделайте uid и gid настраиваемыми для общих томов

Созданный на 23 июл. 2014  ·  141Комментарии  ·  Источник: moby/moby

Предоставьте возможность настраивать владение общими томами.

Например, мой текущий вариант использования - запустить logstash-forwarder в контейнере, который имеет / var / lib / docker общий доступный только для чтения том с хоста.

Поскольку / var / lib / docker установлен на 0700 root: root на хосте, я не могу получить доступ к тому как пользователь без полномочий root.

Я хотел бы иметь что-то вроде NFS, где можно сопоставить uid и gid с хоста пользователям и группам на клиенте.

То есть docker run -v / var / lib / docker: / var / lib / docker: ro : $ user: $ group сделает том доступным в контейнере как доступный только для чтения, принадлежащий $ user: $ group.

kinfeature

Самый полезный комментарий

Нам действительно нужно кроссплатформенное решение (не gosu) для сопоставления uid / gid. Одна только эта проблема наносит огромный ущерб тому, как докер воспринимается новичками.

Все 141 Комментарий

Я не знаю, как они это реализовали, и если сопоставимая функция существует в Linux, но в OS X существует возможность «игнорировать право собственности» на том. Фактически это заставит _ любого_ пользователя видеть файлы / каталоги, как если бы они были владельцем.

Хотя это не подходит для всех случаев, это может быть хорошим дополнением.

gh # 5910 как бы обрабатывает это со стороны SELinux.

ссылка: # 5910;)

Изменение SELinux фактически меняет метки содержимого. Возможно, вы можете внести изменения на хосте. Я не знаю другого способа сделать это для UID / GID. Но выполнение команды chown -R $ UID: $ GID в точке монтирования.

Или вы можете добавить этот тип доступа с помощью ACL. Но я думаю, вам нужно будет изменить каждый INODE в точке монтирования.

Мне тоже нужна эта функция.

Например, я хочу создать веб-контейнер и прикрепить к нему тома с веб-сайтами и конфигурациями, чтобы этот контейнер был полностью универсальным для любого количества веб-сайтов.

Однако мне нужен доступ через git для отправки кода в репозиторий веб-сайта. Поскольку я хочу, чтобы мои приложения были изолированы - я хочу, чтобы каждый каталог веб-сайта принадлежал отдельному пользователю / группе, и было бы здорово, если бы файлы, записанные контейнером Docker в том, принадлежали этому отдельному пользователю / группе.

+1 за эту функцию.
Я не понимаю, как без него могут работать тома чтения / записи. Ожидание того, что guid / uid на образе и на хосте будут одинаковыми, является строгим требованием, несовместимым с принципами изоляции Docker.

Я лично работаю над этим с уродливыми и медленными командами useradd / groupadd для моих инструментов разработки Dockerized: https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/bin-docker/nspire-docker

Я могу полностью упустить суть. Но я боролся с аналогичной проблемой, когда я хочу убедиться, что у пользователя http есть разрешения на запись в / var / log, который является томом и, вероятно, с хоста с root: root в качестве владельца.

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

(удаленный комментарий - неправильная вкладка, извините)

Я обошел это в Ubuntu за пределами Docker. Установите пакет bindfs и привяжите каталог с содержимым тома к другому пути, сопоставляя UID и GID с теми, которые используются внутри контейнера:

sudo bindfs -u UID -g GID oldpath новый путь

Затем используйте newpath в качестве тома докера. Oldpath по-прежнему показывает правильное владение для хоста, newpath для гостя.

@jjv проблема в том, что bindfs ДЕЙСТВИТЕЛЬНО медленный.

@ cpuguy83 да, это далеко не оптимально, но, возможно, поможет кому-то в подобной ситуации. Это должно было заставить что-то работать внутри виртуальной машины разработки (vmhgfs не позволяет устанавливать UID / GID), в то время как в производстве UID и GID все еще должны совпадать между хостом и гостем ...

На самом деле было бы неплохо, если бы при реализации docker использовался тип функциональности bindfs, при условии, что это не сильно снижает производительность. Таким образом, вам не нужно будет следить за тем, чтобы контейнер запускался от имени правильного пользователя. Также должна быть возможность использовать логические имена вместо буквальных uid / gid.

@jsternberg Это ОГРОМНЫЙ хит в производительности. В значительной степени похоже на использование общих папок vbox.

+1

я думаю, что Docker определенно нуждается в этой функции для локальных сценариев использования. И в таком случае я хочу, чтобы эта функция поддерживала как Windows, так и OSX.

Бродяга, похоже, поддерживает это, сопоставляя UID / PID пользователя хоста с бродячим пользователем. Но для целей разработки я действительно хочу использовать Docker вместо Vagrant, поскольку он намного легче, чем Vagrant, для запуска приложений с несколькими хостами.

Скажите, что мне здесь не хватает (у меня нет опыта работы с Go), но разве функция Go Mount () не принимает флаги? Разве мы не могли допустить такую ​​команду, как
-v host/folder:container/folder -mount-as user:group
Не могли бы вы просто получить uid / gid с поиском (https://golang.org/src/os/user/lookup_unix.go)
а затем передать их (uid = 1, gid = 1) в качестве флагов в Mount ()? (https://golang.org/src/syscall/syscall_linux.go?s=19154:19249#L754)

@krisgraham bind

Также отделение опции -v от опции --mount-as вызывает путаницу, когда есть несколько опций -v

Какой хороший обходной путь для этого? Я бы хотел использовать Docker для активной разработки, и отсутствие какого-либо смонтированного тома на самом деле не вариант, так как мне придется перестраивать каждый раз, когда я вношу изменения в свой код.

Причина, по которой я хочу использовать Docker для активной разработки, заключается в том, чтобы он соответствовал моей производственной среде.

@berfarah Я использую докер для активной разработки каждый день.
Редко бывает, когда приходится возиться с химической завивкой.
Если вы используете boot2docker в OSX, убедитесь, что ваш рабочий каталог находится в / Users, и все будет в порядке.

@ cpuguy83 Спасибо за быстрый ответ. У меня проблемы с разрешениями в среде rails, в которой нельзя записывать журналы, и иногда возникают точки сбоя из-за разрешений. Это связано с тем, что у моих сервисов UID отличается от UID одного из файлов.

@berfarah Мой обходной путь - написать мои файлы докеров таким образом, чтобы пользователи / группы контейнеров, которым принадлежит код, имели тот же UID / GUID, что и мой пользователь хоста. Например, поскольку UID моего хост-пользователя равен 1000:

RUN \
    groupadd code_executor_group && \
    useradd code_executor_user -g code_executor_group -u 1000

@berfarah Есть журналы для перехода на стандартный вывод / стандартный поток для RAILS_ENV = development?

@ cpuguy83 Эта проблема не влияет на OSX; thaJeztah прокомментировал 24 июля 2014 г .:

в OS X существует возможность «игнорировать владение» томом. Фактически это заставит любого пользователя видеть файлы / каталоги, как если бы они были владельцем.

@ncjones, на самом деле, то же самое относится и к OS X. "Тома", о которых я там говорил, - это

Мой комментарий должен был сообщить, возможно ли что-то _подобное в Linux (то есть внутри виртуальной машины Boot2Docker)

Извините за путаницу.

@ryneeverett Спасибо, это полезно. Затем вы просто измените разрешения на 775 с 755 и 664 с 644 соответственно, где вам нужно? редактировать: Навыки чтения!

@ cpuguy83 Спасибо! Это кажется более ограничивающим исправлением, чем решение @ryneeverett , поскольку это не совсем то, что я могу просто переносить во все проекты.

@berfarah Рад, что вы нашли это полезным. Да, я просто проверяю, что у моих файлов хоста есть правильные разрешения, и Docker сохраняет их в томах.

+1

Это то, что было бы чрезвычайно полезно для общих томов через докер, и решает мою проблему безопасности:

  • Общие тома, где uid и gid контейнера случайно сопоставляются с привилегированным пользователем без полномочий root на хосте. (например, файлы, созданные контейнером на хосте, отображаются на пользователя, который может использовать sudo без пароля, получать доступ к другому ограниченному контенту и т. д.)

Исправить это было бы очень удобно для корпоративных пользователей, использующих множество контейнеров с Apache или некоторым промежуточным программным обеспечением и совместно использующих тома журналов и / или различные каталоги содержимого / загрузки. У меня также лично были проблемы с этими разрешениями при контейнеризации приложений для конечных пользователей в Linux (например, syncomm / spotify). Многие современные обходные пути сами по себе проблематичны. В конечном итоге это должно быть исправлено в докере. Мне особенно неудобно запускать сценарии оболочки root в качестве точки входа, особенно когда эта проблема подчеркивает, как uid / gid 0: 0 в контейнере будет отображаться на root на моем хосте. Мне нравится первоначальное предложение «docker run -v / var / lib / docker: / var / lib / docker: ro : $ user: $ group».

@syncomm Я бы
Docker не может делать предположений о праве собственности на ваши данные.

Подход, который вы выделяете в нижней части своего комментария, был бы осуществим, если бы мы автоматически сопоставили эти реальные файлы с fs на основе fuse, где мы могли бы изменять uids / gids ... и это могло бы значительно повлиять на производительность.

И скоро uid 0 в контейнере не будет uid 0 на хосте ... что также усложняет владение файлом.

Это дубликат номера 2259?

@ cpuguy83 Спасибо за отзыв, хотя я не уверен, что вы имеете в виду,

Я согласен, что, как и обходной путь bindfs, создание обертки предохранителя повлечет за собой серьезные накладные расходы. Однако выход из этой головоломки должен быть без огромных штрафов. По сути, контейнер ведет себя правильно (как если бы это был отдельный уникальный компьютер от хоста), и когда мы монтируем каталог хоста как том, он (правильно) видит там файловую систему POSIX, разрешения и все остальное. К сожалению, из-за этого очень сложно согласованно обмениваться данными между двумя «хостами». Для этого используются такие вещи, как nfs, cifs и т. Д., Которые поддерживают отображение uid и gid - я бы подумал, что здесь может быть параллель в решении проблемы. Честно говоря, мне нужно больше копаться в репо, чтобы выяснить, где это происходит в коде, и лучше понять это.

Когда будут отменены упомянутые вами изменения прав собственности на файлы? Если uid 0 НЕ является одинаковым для контейнера и хоста, мне будет намного удобнее создавать точку входа для сценария корневой оболочки. Затем нужно просто выполнить предлагаемый обходной путь: передать правильный uid / gid в качестве env и выполнить добавление при запуске контейнера.

@syncomm К сожалению, я не слишком осведомлен, не обернув их в какую-то другую файловую систему, которая может быть смонтирована с настройками uid / gid.

В конечном итоге это похоже на то, что требует поддержки ядра для полного двунаправленного переназначения UID и GID, и даже не выглядит простым в управлении.

Для сценариев, не зависящих от производительности, возможно, что-то можно сделать с помощью FUSE.

По-прежнему +1 для сценариев использования в разработке, так как у меня дома остаются файлы, принадлежащие root.

Для моего случая использования было бы достаточно, если бы докер мог просто применить настраиваемую метку uid / gid и selinux к тому хосту, когда он создает его, оставляя только разрешение и метки, если каталог уже существует. В настоящее время я могу обойти это, имея отдельную точку входа для изображения, которое запускается от имени пользователя root, чтобы исправить разрешение на том.

@ibukanov он не может применять uid / gid, но

@ cpuguy83 какова техническая причина невозможности применить пользовательский uid / gid при создании каталога тома хоста?

@ibukanov См. комментарии выше.

@ cpuguy83 Я просто не понимаю из комментариев, в чем проблема. В моем случае мне не требуется переназначение uid / gid. В настоящее время внутри контейнера при запуске от имени пользователя root я могу chown uid:gid /host_volume && chmod 770 /host_volume . Что было бы неплохо, если бы докер мог делать это самостоятельно при создании каталога на хосте за / host_volume. Таким образом, мне не нужно было бы использовать дополнительную точку входа в контейнере только для выполнения вышеуказанной операции в качестве корневого контейнера и всегда можно было запустить код, используя некорневую учетную запись.

@ibukanov А, это другое дело.
Docker не намеренно вносит изменения в каталоги хостов.
Если мы сделаем # 9092, тогда, если docker создал каталог, он будет обрабатывать его как обычный том (то есть скопировать все на пути к тому в контейнере на хост и chmod / chown, как это было в контейнере).

@ cpuguy83 - ну, докер что-то меняет на хосте, когда создает недостающий том хоста. Но # 9092 звучит так, как будто это действительно решит мой вариант использования.

@ cpuguy83 написал:

И скоро uid 0 в контейнере не будет uid 0 на хосте ... что также усложняет владение файлом.

Есть ли проблема для отслеживания этого? Мне не удалось его найти.

Спасибо!

Есть ли проблема для отслеживания этого? Мне не удалось его найти.

@dato Найдите «Пространство имен пользователей»; начальную реализацию можно найти здесь: https://github.com/docker/docker/pull/12648 и здесь https://github.com/docker/docker/pull/11253

Но до этого есть различные обсуждения / проблемы :)

+1

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

Я использую образ nginx и подключаю том к / usr / shared / nginx / html для локальной разработки. Nginx работает как www-data , но том монтируется как 1000:staff поэтому я получаю 403 forbidden .

@MrMMorris Я не думаю, что это chmod a+r для своих файлов.

@ncjones chmod / chown, похоже, не влияет на разрешения в контейнере

Я так смущен, потому что клянусь, это сработало во многих моментах во время моего использования ...

Хорошо, это неловко ...

Кажется, что либо после обновления до версии 1.3.0rc-1 (вероятно, нет), либо после удаления всех моих контейнеров / изображений и повторного запуска docker-compose up все исправлено .... Больше нет 403 forbidden

Я знал, что это работает раньше, поэтому я использовал старый подход rm -rf * ..

Мне тоже нужно как-то решить эту проблему. У меня есть образ докера, который я использую для выполнения тяжелой работы по компиляции, которую необходимо изолировать. Таким образом, контейнер должен подняться, получить некоторый внешний ввод, обработать, затем он будет производить двоичные файлы (вывод). Без надлежащего управления разрешениями было кошмаром пытаться заставить это работать. Мои изображения должны быть переносимыми, поэтому я не могу много думать о хосте.

@alercunha В вашем случае звучит нормально использовать одного пользователя внутри контейнера докеров, то есть компилировать как root

@alercunha
Мы обошли эту проблему в настройках сборки, заставив контейнер Docker обрабатывать выходные данные сборки. Наш Dockerfile будет содержать что-то вроде:

env USER_ID 1000
env GROUP_ID 1000
cmd bash -lc '\
  build.sh && \
  chown -R $USER_ID:$GROUP_ID build \
'

Фактический uid / gid пользователя хоста Docker может быть затем предоставлен контейнеру при запуске. Например, команда сборки Jenkins будет использовать что-то вроде:

docker run \
  -e USER_ID=`id -u` \
  -e GROUP_ID=`id -g` \
  -v $basedir:/workspace

@motin Сборка с правами root - это то, чего я пытаюсь избежать, поскольку я использую docker / buildroot для создания нескольких сторонних проектов. Идея состоит в том, чтобы иметь некоторую защиту от того, что исходный код испортит мою среду сборки. Так что сборка с правами root не кажется хорошей идеей.

@ncjones Спасибо! На самом деле это хорошая идея, может сработать как решение в моем конкретном случае.

@alercunha В этом случае, возможно, стоит подумать об использовании отдельных изображений / контейнеров для каждого стороннего проекта. Это также могло бы принести больше пользы сообществу открытого исходного кода, например, если бы вы отправили официальные образы докеров для сборки каждого из этих сторонних проектов.

Для предоставления всех привилегий www-data вы можете использовать:

RUN usermod -u 1000 www-data

Возникла проблема при выполнении задания в докере на смонтированном томе. Полученные файлы принадлежали пользователю root и не управлялись пользователем, выполняющим команду docker. Текущий обходной путь - выполнить следующее после задания для исправления разрешений.

docker run -t --rm \
    -v $PWD:/usr/src/app \
    -w /usr/src/app \
    debian:wheezy chown -R $(id -u):$(id -g) ./

Возможно ли, чтобы докер изменил разрешение подключенных томов на основе хоста, которые должны принадлежать пользователю, указанному в команде USER файла DockerFile? Очевидно, что разрешения должны быть настраиваемыми, но мы можем сделать это по умолчанию.

@ mig-foxbat
Для моих целей было бы достаточно, если бы докер просто установил право собственности и разрешение на каталог хоста из точки монтирования в образе, когда каталог хоста создается в первый раз. Если каталог хоста уже существует, докер может оставить его в покое.

@ mig-foxbat & @ibukanov обязательным предварительным условием для меня при открытии этой проблемы было то, что разрешения в файловой системе хостов не меняются (например, есть некое виртуальное отображение в контейнере, подобное тому, что можно сделать с _NFS_).

То, что вы пытаетесь сделать, можно легко сделать сегодня, запустив _chown_ в каком-нибудь сценарии запуска в вашем контейнере.

Мне нравится будущая архитектура подключаемого модуля тома, но я бы предпочел, чтобы команда Docker добавила эту функцию. Docker работает хорошо, пока вы не используете тома с пользователем без полномочий root в своем контейнере. Затем, когда что-то (например, ведение журнала) не работает, вы либо бросаете свой ноутбук через окно Starbucks, либо находите элемент stackoverflow, упомянутый выше.

+1 Я бы хотел, чтобы в контейнерах запускались приложения от имени пользователя без полномочий root, что усложняется из-за этой проблемы.

Почему бы не реализовать эту функцию, используя возможность LXC id_map?

Я только что заметил, что ответ на «id_map» (также известный как поддержка пространства имен пользователей) уже упомянут выше @thaJeztah

Хотя для установки разрешений требуется немного дополнительной работы, мы запускаем десятки контейнеров без полномочий root и избегаем проблем с разрешениями. Большинство наших контейнеров данных начинаются с чего-то вроде:
ENV CONTAINER_USER консул
ENV CONTAINER_UID 312312
ЗАПУСТИТЬ adduser -D $ CONTAINER_USER -u $ CONTAINER_UID
ЗАПУСК mkdir -p / var / consul /
CMD chown $ CONTAINER_USER. $ CONTAINER_USER / var / consul /

Фактический контейнер запуска аналогичен с точки зрения установки информации UID / useradd. Это некоторая повторяющаяся работа (необходимость установки UID как для контейнера данных, так и для контейнера запуска), однако это довольно незначительно. Наличие разрешений на изменение докеров или разрешений на карту на лету добавило бы некоторой приличной сложности, и пользователям пришлось бы быть более осторожными с точки зрения безопасности. Я также за все, что помогает снизить сложность командной строки, поэтому, если все в файле dockerfile само по себе, то все, что происходит, немного проще.

Теперь есть примечание выше о попытке доступа к файлам хоста в контейнере с каким-то сопоставлением. Я считаю, что это, безусловно, рискованное предложение. Часто попытка совместного использования файлов без прямого сопоставления хостов, вероятно, является лучшим решением, поскольку в противном случае вы несколько инвертируете безопасность докеров. Вместо контейнера, имеющего меньше разрешений, чем в противном случае, вы говорите о контейнере, работающем без полномочий root и имеющем доступ корневого уровня (предполагаемый вариант частого использования) для размещения файлов. Групповые разрешения или другие решения, которые, как мне кажется, должны выиграть в большинстве ситуаций.

Я работал над этим с помощью сценария оболочки точки входа, который перехватывает смонтированный каталог и выполняет подкоманду через su.

Пример в контейнере solr, где каталог / data смонтирован как том с хоста:

#!/bin/bash

chown -R $SOLR_USER:$SOLR_USER /data

su -c "$@" -m $SOLR_USER

_ПОЛЬЗОВАТЕЛЬСКИЙ ОПРОС_

_ Лучший способ получать уведомления об изменениях в этом обсуждении - это нажать кнопку «Подписаться» в правом верхнем углу. _

Люди, перечисленные ниже, оценили ваше содержательное обсуждение случайным +1:

@jcercurati
@iangelov
@scue
@razvanphp
@призрак
@andrerocker
@anandnalya
@ddopson
@hason
@hadim
@iyn
@cgrantcharovtp
@sandytrinh
@gomex
@DrBenton
@tehmaspc
@segphault
@avaz
@edavism
@ayeo
@stanislavb
@smebberson
@ tony-kerz
@msierks
@pdonorio
@ samsong8610
@ qm78
@joshughes
@roelvanduijnhoven
@vladimirbright
@ ava-dylang

Когда вы говорите что-либо в этих потоках, пользователь автоматически подписывается, так что да, все эти люди подписаны, если они не отказались от подписки дополнительно, намеренно. (также не уверен, _кто_ вы имеете в виду your )

Это определенно необходимо. Docker должен правильно переназначить UID. В противном случае все, что создается из контейнера в том ОС хоста, принадлежит пользователю root. Обходной путь ужасен - смена пользователей внутри контейнера, что приводит к всевозможным осложнениям, приходится ломать голову везде, Dockerfile уродливо разрастается. И, что хуже всего, жестко запрограммированные UID делают контейнеры непереносимыми!

+1 Эта функция была бы очень признательна, поскольку я хочу избежать переключения между контейнером докеров и моей хост-системой, просто чтобы избежать перезаписи идентификатора пользователя в файлах.

Получить настройку UID можно прямо сейчас, но со следующими ограничениями:

  • Настройка Uid возможна, если контейнер принимает необходимые uid через переменную окружения. Это дает хосту полный контроль над uid (ами), которые использует контейнер, и имеет дополнительное преимущество: несколько переменных могут быть установлены на одно и то же значение uid. Переназначение Uid не может поддерживать отображение нескольких uid контейнера на один uid хоста, так как отображение должно быть 1: 1. Например, если желаемое сопоставление фактически заключалось в том, что приложение должно работать как uid = 0, вы могли бы сделать это путем внедрения переменных, но не путем переназначения uid. См. Решение @ncjones и @mitchcapper выше.
  • В частности, корневой uid = 0 не может быть изменен на другое значение, кроме как путем переназначения: # 12648.

Практически во всех современных средах веб-разработки есть папка журналов и папка кеша внутри проекта, определенная в конфигурации проекта и доступная через смонтированный том. Сначала я использовал vboxfs, но был слишком медленным. Я нашел docker-machine-nfs для создания монтирования NFS, и это быстро, но теперь мои веб-файлы в контейнерах принадлежат 502: dialout и не могут быть chmod или chown, поэтому мое веб-приложение не запускается. Я пробовал докер-бродягу, но для него требуется бродяга со всеми разными env-переменными и конфигурациями, и он еще не работает с докер-машиной. Даже если это ручной процесс на короткий срок, есть ли обходной путь, чтобы добавить пользователя 502 в www-data или что-то в этом роде? Это все, что мне нужно для работы!

+1

Для тех, кто следит за этим; в настоящее время существует PR для экспериментальной функции, которая рекурсивно изменяет владельца прикрепленных к привязке файлов. Однако его следует использовать с осторожностью, потому что эта функция изменит файлы на хосте (что может быть не во всех случаях); см. https://github.com/docker/docker/pull/14632 (и https://github.com/docker/docker/pull/16767)

+1

Кстати, я решил эту проблему при использовании ACL

@kvaps ,

@posita , держу пари, что @kvaps говорит о ACL POSIX . Если я прав, это не то же самое, что запрос OP.

@posita , @denydias , извините за длинный ответ. Да, я об этом говорю.
У меня много контейнеров, таких как owncloud, samba и minidlna. Все работают с разными uid и gid.
Все они работают с одними и теми же файлами. Что бы каждый мог читать и писать файлы, я смонтировал файловую систему с опцией acl на хост-машине и дал всем права uid и gid для этих файлов просто, например, команду chown :

# give access for owncloud (apache uid 33):
setfacl -R -m "u:33:rwx" /data
# give access for samba (uid 1000):
setfacl -R -m "u:1000:rwx" /data
# give access for minidlna (uid 997):
setfacl -R -m "u:997:r-x" /data
# preserve this permissions for new files and folders:
setfacl -R -d -m "u:33:rwx" /data
setfacl -R -d -m "u:1000:rwx" /data
setfacl -R -d -m "u:997:r-x" /data

@kvaps , команда setfacl не работает в Dockerfile . Пример:

FROM nginx

ADD data/conf /etc/nginx

RUN mkdir -p /etc/nginx/sites-enabled

VOLUME /etc/nginx

RUN setfacl -dR -m u:1000:rwx /etc/nginx && setfacl -R -m u:1000:rwx /etc/nginx

Результат:

root<strong i="12">@3975ac4fba98</strong>:/etc/nginx# getfacl sites-enabled/
# file: sites-enabled/
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

ACL работают только после монтирования на хост-машине и запуска setfacl . Версия докера:

Client version: 1.7.1
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 786b29d
OS/Arch (client): linux/amd64
Server version: 1.7.1
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 786b29d
OS/Arch (server): linux/amd64

Это очень просто сделать правильно, а также очень просто испортить. Так что не облажайтесь!
Правильный способ сделать это: при первом запуске контейнера хост вводит те идентификаторы uid, которые контейнер должен использовать (как уже описано выше).
Худший способ сделать это: ожидать, что контейнер наложит на хост свои требования uid. Это неправильно, неправильно, неправильно. Например, рассмотрим два контейнера с общим монтированием: один контейнер записывает файлы для обслуживания, а другой контейнер запускает httpd для обслуживания файлов. Теперь, если у обоих этих контейнеров есть конкурирующие определения uid, эта система будет в худшем случае сломана, а в лучшем - неполна. Настраиваемые списки ACL не будут иметь никакого смысла для хоста и, вероятно, будут более широкими, чем необходимо, а это означает, что теперь это проблема безопасности. Пожалуйста не делай этого!! Делай это правильно.

Согласовано. Оставить сопоставление между UID и контейнером - достаточно хорошее решение. Просто хотел, чтобы докер был примером и поддерживает такие сопоставления UID / GID в официальных образах докеров.

Решаемые во время выполнения, без chown .

Я использовал что-то близкое к решению @ncjones , но мне не нужны файлы chown потому что я не хочу, чтобы они изменялись на хосте. Поэтому я решил изменить UID при запуске контейнера.

Я создаю специального пользователя в моем Dockerfile :

RUN adduser --no-create-home --disabled-login --gecos "" username --uid 1000

Я определяю сценарий запуска в моем Dockerfile :

CMD ["/run.sh"]

У меня есть эта строка в моем сценарии /run.sh :

usermod -u $USER_ID username

Теперь я могу выбрать USER_ID при запуске контейнера:

docker run -e USER_ID=$(id -u)

Удалось решить эту проблему с помощью новых аргументов dockerfile. После сборки контейнера ничего особенного делать не нужно, поэтому я подумал, что поделюсь. (Требуется Docker 1.9)

В Dockerfile:

# Setup User to match Host User, and give superuser permissions
ARG USER_ID=0
RUN useradd code_executor -u ${USER_ID} -g sudo
RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER ${USER_ID} 

Затем построить:

docker build --build-arg USER_ID=$(id -u)

В остальном все как обычно :)

Редактировать:
Я написал этот пост не по тому поводу (это был еще один, связанный с boot2docker).
Извините.

@ pa-de-solminihac usermod -u $USER_ID username изменит идентификатор пользователя username и вызовет смену владельца файлов в HOME username , но каждый файл, ранее принадлежавший username за пределами его ДОМА, вероятно, станут нечитаемыми / незаписываемыми, поскольку теперь они принадлежат другому пользователю

@riquito Я использую его с выделенным пользователем, созданным в Dockerfile :

adduser --no-create-home --disabled-login --gecos "" username --uid 1000

Следовательно, нет файлов, которыми ранее владел username . Так что, думаю, проблем нет;)

К вашему сведению, setfacl _не_ работает с отслеживанием томов до OS X:

root<strong i="7">@0da3c867240d</strong>:~# setfacl --default --recursive --modify u:500:rwx --modify g:500:rwx /opt/test
setfacl: /opt/test: Operation not supported

(В этом случае /opt/test размещается в OS X через машину Docker и Boot2Docker. См. Также boot2docker / boot2docker # 581.)

@posita Используете ли вы

@ ava-dylang, это хороший аргумент. Вышеупомянутое выполняется через Docker Machine с драйвером Parallels , который использует встроенную реализацию общих папок Parallels, которая выглядит так же ограниченно. (См. Также https://github.com/docker/machine/issues/13#issuecomment-164320881 относительно предложения для этих типов сред.)

FWIW, у меня были проблемы с владением файлами в моей утилите Scuba .

Я обошел проблему, добавив сценарий "init", который создает пользователя в контейнере с тем же UID / GID, что и вызывающий пользователь на хосте. См. JonathonReinhart / scuba # 11 и JonathonReinhart / scuba # 13.

Теперь файлы, созданные в контейнере, выглядят точно так же, как они были созданы на хосте.

_Обновление: _ Это вызвало проблемы (JonathonReinhart / scuba # 22). Вместо этого я исправил это, сгенерировав свои собственные /etc/passwd и друзей на основе uid / gid пользователя хоста, и ввел его в контейнер (см. JonathonReinhart / scuba # 24).

+1

Чтобы сделать его более удобным и безопасным, когда хост работает в мультитенантном режиме.

У меня были проблемы с разрешениями при таких установках Wordpress, когда вы делитесь всем Wordpress от хоста до контейнера с томом.

В моем стеке у меня есть базовый образ, который представляет собой debian с моими базовыми модификациями, и все остальные образы будут построены из этого образа.

В базовом образе у меня есть эта часть:

### Start of Nginx WEBSERVER setup
RUN mkdir -p /var/www
# Modify www-data user and set UID, GID to 500
# https://muffinresearch.co.uk/linux-changing-uids-and-gids-for-user/
RUN groupmod -g 500 www-data \
    && usermod -u 500 www-data \
    #&& `find / -user 33 -exec chown -h 500 {} \;` \
    #&& `find / -group 33 -exec chgrp -h 500 {} \;` \
    && usermod -g 500 www-data \
    && chown -R www-data:www-data /var/www \
    && chmod g+s /var/www
### End of Nginx WEBSERVER setup

www-data не создается при установке php или nginx. Это определенный по умолчанию пользователь / группа в Debian и, возможно, других дистрибутивах. Некоторые установки PHP и Nginx предлагают использовать этого пользователя в своих файлах конфигурации.

Если UID / GID вашего хост-пользователя равен 500 (по умолчанию UID / GID первого пользователя без полномочий root в Linux равен 500 или 1000), то этот скрипт изменяет UID / GID пользователя www-data на 500 с 33. Таким образом, если вы делитесь чем-либо с хоста, Docker считает, что эти файлы и папки принадлежат пользователю www-data !

В ваших файлах настроек PHP-FPM также задайте для пользователя и группы значение www-data .

В вашем файле Dockerfile nginx вы также должны установить это:

# Allow Nginx to access /var/run/php-fpm/php-fpm.sock
RUN usermod -aG www-data nginx

Таким образом, пользователь nginx может получить доступ к файлам, принадлежащим www-data (вы можете определить имя пользователя nginx в файлах конфигурации nginx).

После этого взлома моя установка Wordpress не имела НИКАКИХ проблем с разрешениями! Все файлы находятся на хосте + обновление Wordpress работает безупречно!

@DJviolin Я не уверен, что подобная проблема является подходящим местом для учебника по Wordpress, и не

  1. То, что вы опубликовали, делает множество предположений об установке - например, значения UID / GID, имена пользователей и групп и т. Д. Это не очень переносимо между дистрибутивами.
  2. Что еще более важно, предоставление общего доступа (0777) для всей вашей установки Wordpress чрезвычайно опасно и явно не рекомендуется в официальной документации WP. Более того, когда все это смонтировано с хоста, вы только что разрешили произвольным загрузкам из Интернета записывать в файловую систему _host_.

@jantman Извини, я плохо. Похоже, что первый взлом также решает проблемы с разрешениями. Нет необходимости изменять какие-либо разрешения по умолчанию.

Очевидно, каждому нужно узнать UID своего хост-пользователя

Пока докер не решит эту проблему, предположения останутся.

Мое решение такое же, как @JonathonReinhart или @ pa-de-solminihac.

Вы можете сделать это, создав локальные тома, он просто приземлился в мастер https://github.com/docker/docker/pull/20262.

Закрытие как исправлено.

Привет, мне также пришлось найти обходной путь в моем файле докеров:

...
COPY start.sh /root/start.sh
CMD /root/start.sh

а затем в start.sh

usermod -u $USER_ID www-data
exec php-fpm

Поскольку $ USER_ID может быть введен в качестве параметра среды, можно использовать этот образ докера без изменений.

В любом случае, я думаю, что для такого рода вещей должно быть больше встроенных функций, и мне интересно, как использовать эти локальные тома, предложенные @calavera , может кто-нибудь привести пример?

@ keywan-ghadami Я тоже ломал голову над локальными томами. Проблема в том, что вам нужно сначала создать файловую систему (или использовать tmpfs). Поэтому он не использует / var / lib / docker. Фактически, вы не можете использовать подкаталог _любой_ существующей FS, потому что привязки не поддерживают параметр uid . Я не знаю, для чего нужны локальные тома; вы также можете создать и смонтировать FS самостоятельно, а затем использовать обычный хост-том ( -v my-created-fs:container-mount-point ).

Я довольно поздно зашел в эту ветку, но была ли решена эта проблема? Это не на 100% ясно из всех упомянутых здесь проблем. @brthor, похоже, имеет лучшее решение из того, что я вижу, но включает в себя параметры командной строки, которые можно было бы легко добавить в Dockerfile и сделать за кулисами.

Для меня жесткое кодирование UID и GID - плохая идея для переносимости между средами, и я не вижу необходимости добавлять аргументы командной строки каждый раз, когда я загружаю контейнер или создаю образ, когда это может быть простой вариант в Dockerfile. Разве не может быть простой опции в Dockerfile или, возможно, через docker-compose.yml, где вы можете указать какую-то опцию «сопоставить uid с хоста»?

Возможно, там уже есть хорошее решение, но я не могу понять этого из документации или этого потока.

Спасибо @alvinchevolleaux. Я могу подтвердить, что мы уже несколько месяцев успешно используем решение, которое я опубликовал в CI для https://github.com/dotnet/cli .

Рекомендую!

@brthor Да, это то, что у меня было, я добавил export USER_ID=$(id -u) в свой .bash_profile, так что все это автоматически для моих различных сред. Большое спасибо.

Как обсуждалось выше, при совместном использовании содержимого из вашей домашней папки в контейнер добавьте учетную запись пользователя с тем же UID, что и ваш. Вот трюк, чтобы справиться, если ваш UID не равен 1000. Я предполагаю, что каждый пользователь создает свой собственный образ докера из файла Dockerfile.

Ваш Dockerfile должен содержать:

RUN useradd --uid 1000 -m vagrant
USER vagrant

Константа 1000 заменяется вашим фактическим UID с помощью _git filter_. Выполните на своем хосте следующее:

git config filter.uidfix.smudge "sed s/1000/$UID/g"
git config filter.uidfix.clean "sed s/$UID/1000/g"

Наконец, добавьте файл .gitattributes чтобы применить фильтр git:

Dockerfile filter=uidfix

Это работает путем замены 1000 на ваш фактический UID, когда вы проверяете файл Docker, _smudging_ файл. Git _ очистит_ файл (вернув 1000 ), когда вы зафиксируете. Любые команды, выполняемые в контейнере, выполняются от имени пользователя vagrant с правильным UID.

Похоже, этот билет следует открыть повторно, поскольку все предлагаемые здесь решения - это только обходные пути.
Я нашел хорошее документированное и более полное решение в https://github.com/rocker-org/rocker/blob/master/rstudio/userconf.sh
Он использует аргументы времени выполнения, что позволяет использовать предварительно созданные изображения, что невозможно с фильтром git.

@calavera Я не понимаю вашего решения.

например

$ mkdir /tmp/test
$ sudo docker volume create --name=test -d local --opt type=nfs --opt device=/tmp/test:/data --opt o=notime,nosuid,uid=11459,git=11459
$ sudo docker run -t -i -v test:/tmp fedora bash -i
[.. $] touch /tmp/foo.txt
[.. $] exit
$ ls -la /tmp/test

Когда я смотрю в каталог / tmp / test, там нет файлов. Не похоже, что папка / tmp / test монтируется в контейнер ... Скорее, создается том контейнера. Кого не очень хочу хочу.

Я не могу найти никакой документации, в которой говорилось бы, какие допустимые параметры --opt. Так что я действительно догадываюсь, как это должно работать.

Пожалуйста, откройте эту проблему повторно. Новый локальный драйвер, похоже, совсем не решает проблему монтирования каталогов локального хоста с выбранными идентификаторами пользователя.

@calavera
Не могли бы вы прокомментировать, как мы можем решить проблему удаления файлов с правами суперпользователя с томами локального хоста? Я часто видел, как эта проблема возникает, особенно при использовании докеров для сценариев CI.

Глядя на связанный PR, я не вижу сразу ничего очевидного, но я уверен, что что-то упускаю 😄

Я использовал варианты этого обходного пути в своих контейнерах, такие как docbill / docker-force. Однако мне приходит в голову, что более чистое решение - это контейнер, который отвечает только за выполнение squashroot ...

Использование чего-то вроде bindfs для локального должно помочь. Вы можете запустить его с помощью -o map = $ (id -u) / root: @ $ (id -g) / @root (при условии отсутствия пространства имен пользователя), и вы должны видеть файлы как свои за пределами контейнера, пока они принадлежат корень внутри него.

@ktosiek Спасибо, похоже, у него есть потенциал. Не могли бы вы опубликовать полный пример команды docker run или сеанса консоли?

Может ли кто-нибудь опубликовать обновление статуса по этой проблеме: была ли она закрыта как «не исправит» или это действительно было реализовано? Цепочка довольно длинная, поэтому, пожалуйста, простите меня, так как я не могу сразу увидеть, какое разрешение.

@quinncomendant см. https://github.com/docker/docker/issues/7198#issuecomment -191990887
Сообщите, если это не сработает.

Спасибо @ LK4D4.

Подводя итог, можно сказать, что проблема была закрыта с помощью исправления, которое позволяет выбрать монтирование для драйвера тома local .

Насколько я могу судить, нет никаких вариантов для установки user: group в _host-каталоге, смонтированном как том_ (пожалуйста, поправьте меня, если эта опция существует - это то, что я пришел сюда, чтобы узнать).

@quinncomendant правильный; при связывании монтирования каталога хоста вы хотите, чтобы контейнер использовал файлы, которые находятся там, как есть, включая разрешения. Если вы хотите изменить эти разрешения, вам нужно сделать это на хосте перед их монтированием.

@quinncomendant Или,
предоставленное решение на самом деле ничего не делает для решения проблемы
сообщается, и не планируется решение этой проблемы.

6 июля 2016 г. в 17:20 Себастьян ван Стейн [email protected]
написал:

@quinncomendant https://github.com/quinncomendant правильно; когда
bind-монтируя каталог хоста, вы хотите, чтобы контейнер использовал файлы, которые
есть как есть, включая разрешения. Если вы хотите изменить эти
разрешения, вам необходимо сделать это на хосте, прежде чем монтировать их

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/docker/docker/issues/7198#issuecomment -230909967 или отключить звук
нить
https://github.com/notifications/unsubscribe/ADBcWLihVjI1FoSMLKu7DyhwFOpGX0KKks5qTBwMgaJpZM4CQMjR
.

Кажется, это проблема, которая НЕ ИСПРАВЛЯЕТСЯ. Всегда кажется, что аспекты контейнеризации _development_ по-прежнему игнорируются и по-прежнему требуют от нас написания хаков.

Я специально столкнулся с этой проблемой, потому что разработчики, которых я поддерживаю, запускают команды создания файлов проекта изнутри контейнера и на том, смонтированный на хосте (установка этих инструментов на хосте полностью лишает смысла использование контейнера, верно?).

Они хотят быстро перебирать эти файлы, но, как указывали другие участники этого потока, они записываются как uid / gid, под которым работает контейнер, что требует, чтобы они были правильно обработаны на хосте для дальнейшего управления (с помощью IDE например).

В таких случаях действительно должен быть специальный _docker_ способ использовать временные uid / gid.

@boj Это точный сценарий, с которым я столкнулся при разработке Scuba . Мое текущее решение создает во время запуска пользователя в контейнере с тем же uid / gid, что и пользователь хоста. Это не самое простое решение, но оно работает хорошо.

@JonathonReinhart Спасибо, вы немного вдохновили меня.

Я закончил тем, что написал обертку сценария, вызываемую с хоста следующим образом (в данном случае они используют django):

# bin/manage.py
#!/bin/sh

docker run -v $(pwd):/usr/local/prj -it --entrypoint="/usr/bin/python3.4" -w /usr/local/prj -u $(id -u):$(id -g) prj src/prj/manage.py $@

@boj Потенциальная проблема с этим решением ( -u $(id -u):$(id -g) ) заключается в том, что нет записи в /etc/passwd или /etc/group для этого uid / gid в контейнере: https: // github .com / JonathonReinhart / scuba / issues / 11

@JonathonReinhart Отметил. В этом конкретном случае меня интересуют только файлы, записанные на хост разработчика, и что они имеют те же разрешения, что и пользователь хоста.

Не беспокойтесь о том, что на самом деле происходит во время выполнения, это все, что мне действительно нужно.

@JonathonReinhart

Если программному обеспечению в контейнере требуется запись в / etc / passwd или / etc / group, сделайте их доступными для записи всем в образе, а затем добавьте туда необходимые записи при запуске.

Таким образом, решение, упомянутое @JonathonReinhart (отображение uid / gid), решает это.

Похоже, это уже поддерживается в runc (https://github.com/opencontainers/runc/blob/8c9db3a7a5145f6b26c8051af319eee6f72c9ca8/libcontainer/configs/config.go#L19-24). В Docker есть конфигурация userns-remap для демона, здесь нам в основном нужно сделать ее более детализированной (уровень контейнера вместо уровня демона), есть ли какой-либо интерес / план для поддержки этого?

Этот docker-compose.yml не работает:

version: '2'

services:
  app:
    build: ./app
    container_name: myapp
    volumes:
      #- "../app:/root/www/myapp:rw"
      - myapp:/root/www/myapp:rw

volumes:
  myapp:
    driver: local
    driver_opts:
      o: uid=500
      device: ../app

Кто-нибудь может мне сказать, почему? Я следую официальным рекомендациям: https://docs.docker.com/engine/reference/commandline/volume_create/#/driver -specific-options

Можно ли присоединить именованные тома к хосту? С помощью driver_opts вы можете определить uid (и, возможно, gid ?).

+1

+1

@lazyuser @xiaods Пожалуйста, остановитесь с +1. Он не выполняет ничего, кроме рассылки спама всем этим ---> участникам.

@bamarni Да, я думаю, что новая функция пространства имен пользователей может решить эту проблему, но, как вы сказали, ее необходимо реализовать для каждого контейнера. Конечным результатом будет: Контейнер работает как то, что он считает «корневым», но на самом деле это UID / GID, переданный в командной строке docker run . Тогда файлы будут «выходить» из контейнера, принадлежащего соответствующему пользователю.

@lazyuser @xiaods @JonathonReinhart, вам лучше нажать кнопку +1 под описанием проблемы

Или просто нажмите «Подписаться» справа, если вам нужны только уведомления ...

@JonathonReinhart : определенно, я снова просмотрел документ, но, к сожалению, использование всего демона сопоставления вместо каждого контейнера было осознанным решением из-за ограничения:

Примечание. На данный момент действует ограничение на одно сопоставление для каждого демона, поскольку Docker использует слои изображений из своего локального кеша для всех контейнеров, запущенных в экземпляре движка. Поскольку владение файлом должно быть одинаковым для всех контейнеров, совместно использующих один и тот же контент слоя, было принято решение сопоставить владение файлом при вытягивании докера с отображениями пользователя и группы демона, чтобы не было задержки для запуска контейнеров после загрузки контента. Этот дизайн сохраняет ту же производительность для docker pull, docker push и запуска контейнера, которую ожидают пользователи, с отключенными пространствами имен пользователей.

_ (https://docs.docker.com/engine/reference/commandline/dockerd/#/daemon-user-namespace-options) _

Уважаемые @JonathonReinhart , @ pa-de-solminihac и @nalipaz ,
Спасибо за ваши усилия, чтобы научить меня и других не оставлять комментарии, не связанные с проблемой, делая именно это! К вашему сведению, Github не позволяет искать проблемы, на которые вы подписаны, по крайней мере без их комментариев. Для получения дополнительной информации см. Https://github.com/isaacs/github/issues/283. По иронии судьбы проблема Github почти того же возраста, что и проблема Docker, и обе, похоже, имеют одинаковый приоритет.

Всем извините за спам. В первый раз это был обходной путь для вышеупомянутой ошибки github, и на этот раз я просто не смог удержаться от иронии судьбы ситуации.

Я решил это с помощью inotifywait . Вам нужно будет установить inotify-tools, чтобы запустить его внутри вашего образа докера. Вместо этого можно запустить его на вашей хост-системе, но мне нужно было портативное решение.

RUN export DEBIAN_FRONTEND=noninteractive \
  && apt -y update \
  && apt -y install inotify-tools \
  && inotifywait -m -r /mount -e create --format '%w%f' \
    | while read f; do chown $(stat -c '%u' /mount):$(stat -c '%g' /mount) $f; done

Это работает, инструктируя inotifywait следить за любыми новыми файлами или каталогами, созданными в каталоге / mount. Когда он замечает один, он меняет владельца на того же пользователя и группу, что и папка / mount. Я использовал целочисленное представление обоих, на случай, если пользователь / группа хоста не существует в контейнере. Внутри контейнера не имеет значения, кому он принадлежит, потому что все работает как root. За пределами контейнера файловая система хоста показывает то же право собственности, что и любой каталог, смонтированный в / mount.

Я намеренно разработал его так, чтобы устанавливать права собственности только на вновь созданные файлы и каталоги, чтобы сохранить право собственности на уже существующие файлы и каталоги. Это безопаснее, чем убирать все это с помощью инструкции chown -R каждый раз, когда монтируется файловая система. Если для вашего проекта подходят единые разрешения, и вам нужно более простое решение, которое работает более эффективно, посмотрите на

Предупреждение: поскольку для каждого подкаталога будет установлено одно наблюдение inotify, возможно, будет достигнуто максимальное количество часов inotify на пользователя. Максимальное значение по умолчанию - 8192; его можно увеличить, записав в / proc / sys / fs / inotify / max_user_watches.

@ codekitchen-ws Еще одно предупреждение: файл может быть перемещен после создания, но до смены владельца. В зависимости от оболочки вы также захотите заключить в кавычки "$f" (чтобы предотвратить разделение слов в пути).

+1

@briansrepo Это интересный подход. Если это находится в инструкции Dockerfile RUN , которая выполняется во время сборки. Как он мог узнать пользователя docker run во время выполнения?

@btiernay Спасибо! Он не использует UID пользователя, запустившего изображение. Он специально копирует пользователя хоста и группу хостов из любого каталога хоста, смонтированного в / mount. Он не смотрит ни на какие другие файлы или подкаталоги. Пользователь должен убедиться, что разрешения установлены на то, на что они могут писать в хост-системе.

Пример: Предположим, что каталог хоста / var / www / html принадлежит brian: www-data. Вы запускаете образ, который монтирует системный каталог хоста / var / www / html в каталог образа / mount. Затем вы создаете /mount/index.html внутри изображения. Если вы перейдете к проверке права собственности на /var/www/html/index.html в хост-системе, он будет принадлежать brian: www-data.

Основываясь на этом примере, предположим, что у вас есть каталог хоста / var / www / html / upload, принадлежащий www- data: www-data. Имейте в виду, что смонтированный каталог хоста / var / www / html по-прежнему принадлежит brian: www-data. Теперь войдите в образ и создайте /mount/upload/file.pdf. Если вы проверите файл хоста /var/www/html/upload/file.pdf, он будет принадлежать brian: www-data , а не www- data: www-data , потому что смонтированный каталог хоста / var / www / html является принадлежит Брайану: www-data. Есть смысл?

TL; DR: вы передаете user: group, которую хотите использовать, выбирая подключенный каталог хоста к user: group.

@briansrepo спасибо за объяснение. Все это имеет смысл, но мы все еще не понимаем, как это может работать внутри RUN . Я бы подумал, что это нужно будет выполнить в фоновом режиме при выполнении контейнера (т.е. docker run ).

@btiernay Мне тоже нравится эта идея.
@briansrepo, по крайней мере,
Процесс сборки все еще можно решить с помощью чего-то вроде

RUN usermod -u 1000 www-data

Однако это все еще обходные пути.

В моем стеке LEMP у меня есть эта предварительная конфигурация Nginx в моем базовом файле Docker:

### Start of Nginx WEBSERVER setup
RUN mkdir -p /var/www
# Modify www-data user and set UID, GID to 500
# https://muffinresearch.co.uk/linux-changing-uids-and-gids-for-user/
RUN groupmod -g 500 www-data \
    && usermod -u 500 www-data \
    && usermod -g 500 www-data \
    && chown -R www-data:www-data /var/www \
    && chmod g+s /var/www
### End of Nginx WEBSERVER setup

Это взлом, при котором все вновь созданные файлы из сеанса хоста ssh, получающие uid, gid 500 и nginx, в конечном итоге не будут иметь доступа к этим файлам (потому что пользователь или группа с идентификатором 500 не существует в контейнере). Вы можете проверить, какой uid, номер gid вы должны создать для своего пользователя www-data когда вы копируете новые файлы в общий том на хосте из сеанса ssh, а затем вы docker exec в этот контейнер и смотря файлы uid, gid.

Проблема, которую я обнаружил, заключается в том, что если я скопирую новые файлы в общую папку на хост-машине (к которой вы получили доступ через сеанс ssh, как в экземпляре CoreOS в DigitalOcean), Nginx не будет иметь доступа к этим вновь созданным файлам. Поэтому, если вам нужна абсолютная совместимость с привилегиями, вы должны поделиться файлами своего веб-сервера в контейнере Docker при создании контейнеров (по крайней мере, так было год назад, когда я столкнулся с этими проблемами uid, gid с общими томами) .

ИЛИ вы также можете установить службу ssh в контейнер докеров, который разделяет файлы с контейнером nginx, таким образом, если вы копируете / изменяете файлы, они получают правильный uid, gid. Но это противоречит лучшим практикам Docker, согласно которым вы должны использовать docker inspect вместо сеансов ssh, потому что «Docker - это не виртуальная машина» (это было бы слишком простым решением, не так ли?).

На мой взгляд, контейнер Docker должен действовать как служба или исполняемый компонент и не должен брать в заложники мои файлы веб-сервера, если я не хочу. База данных - это другой вид вещей (иногда), но я не понимаю, почему невозможно достичь той же инфраструктуры контейнера Святого Грааля, где все ваши статические файлы, файлы веб-сервера и базы данных находятся за пределами контейнеров (но контейнеры могут изменять их (например, удалять, создавать, изменять), и вы также можете изменять их без каких-либо проблем с привилегиями со стороны хоста.

С помощью docker volume create --opt вы можете определить uid, gid, но это неверно для docker-compose : https://github.com/docker/compose/issues/3715

Нам действительно нужно кроссплатформенное решение (не gosu) для сопоставления uid / gid. Одна только эта проблема наносит огромный ущерб тому, как докер воспринимается новичками.

Мы создали обходной путь для этой проблемы, который изменяет права пользователя / группы и файла контейнера Docker, которые были установлены во время сборки, на UID / GID, с которыми контейнер был запущен во время выполнения.

Инструкции по проекту и установке находятся по адресу: https://github.com/boxboat/fixuid.

Пример: контейнер Docker был построен с использованием пользователя / группы dockeruser:dockergroup качестве UID / GID 1000:1000 . Хост работает как UID / GID 1001:1002 . Изображение запускается с docker run -u 1001:1002 . fixuid будет:

  • измените dockeruser UID на 1001
  • измените dockergroup GID на 1002
  • изменить все права доступа к файлам для старых dockeruser:dockergroup на 1001: 1002
  • обновить $ HOME внутри контейнера до dockeruser $ HOME
  • теперь контейнер и UID / GID хоста совпадают, и файлы, созданные в контейнере при монтировании хоста, будут совпадать

Он может работать как ENTRYPOINT или как часть сценария запуска. Он устанавливается в контейнер как двоичный файл, принадлежащий root с битом setuid , и повышает привилегии для внесения соответствующих изменений. Его следует использовать только в контейнерах разработки.

Если это окажется полезным, Docker Engine может включить часть или всю логику с помощью флагов в docker run

Решено с помощью docker volume .

@hashar как? Вы можете привести пример, пожалуйста

так что для этого все еще нет решения, кроме использования gosu и сценария точки входа ?!

На данный момент, похоже, есть 2 варианта обхода этой проблемы, пока команда Docker не сделает официальное обновление по этому поводу.

Какая жалость, что это все еще проблема. Теоретически существует переназначение userns-remap, но это неудобно для пользователя.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги