Moby: 공유 볼륨에 대해 uid 및 gid 구성 가능

에 만든 2014년 07월 23일  ·  141코멘트  ·  출처: moby/moby

공유 볼륨의 소유권을 구성할 수 있는 옵션을 제공하십시오.

예를 들어 현재 사용 사례는 /var/lib/docker가 호스트의 볼륨으로 읽기 전용으로 공유된 컨테이너 내에서 logstash-forwarder를 실행하는 것입니다.

/var/lib/docker가 호스트에서 0700 root:root로 설정되어 있으므로 루트가 아닌 사용자로 볼륨에 액세스할 수 없습니다.

내가 갖고 싶은 것은 호스트의 uid 및 gid를 클라이언트의 사용자 및 그룹에 매핑할 수 있는 NFS와 같은 것입니다.

즉, docker run -v /var/lib/docker:/var/lib/ docker:ro :$user:$group $user:$group에 속하는 읽기 전용으로 컨테이너에서 볼륨을 사용할 수 있게 합니다.

kinfeature

가장 유용한 댓글

우리는 uid/gid를 매핑하기 위한 크로스 플랫폼 go-to(gosu 아님) 솔루션이 정말로 필요합니다. 이 문제만으로도 초보자가 도커를 인식하는 방식에 막대한 피해를 입힙니다.

모든 141 댓글

나는 그들이 이것을 _어떻게_ 구현했는지 모르겠고, Linux에 유사한 기능이 존재하지만 OS X에는 볼륨에 대한 '소유권 무시' 기능이 존재합니다. 효과적으로 이것은 _any_ 사용자가 파일/디렉토리를 소유자인 것처럼 보이게 합니다.

이것이 모든 경우에 적용되는 것은 아니지만 좋은 추가 사항이 될 수 있습니다.

gh#5910은 SELinux 측에서 이것을 처리합니다.

링크: #5910 ;)

SELinux 변경 사항은 실제로 콘텐츠의 레이블을 변경하는 것입니다. 잠재적으로 호스트에서 변경 작업을 수행할 수 있습니다. UID/GID에 대해 이 작업을 수행하는 다른 방법은 없습니다. 그러나 마운트 지점에서 chown -R $UID:$GID를 수행합니다.

또는 ACL을 사용하여 이러한 유형의 액세스를 추가할 수 있습니다. 그러나 마운트 지점의 모든 INODE를 변경해야 한다고 생각합니다.

이 기능도 필요합니다.

예를 들어 웹 컨테이너를 만들고 웹 사이트 및 구성이 포함된 볼륨을 여기에 연결하여 컨테이너가 모든 웹 사이트에 대해 완전히 보편적이 되도록 하고 싶습니다.

그러나 웹 사이트 저장소에 코드를 푸시하려면 git 액세스가 필요합니다. 내 앱을 격리하고 싶기 때문에 각 웹 사이트 디렉토리를 별도의 사용자/그룹이 소유하고 싶고 Docker 컨테이너가 볼륨에 쓴 파일을 해당 별도의 사용자/그룹이 소유하면 좋을 것입니다.

이 기능에 대해 +1입니다.
읽기/쓰기 볼륨이 그것 없이 어떻게 작동하는지 이해할 수 없습니다. guid/uid가 이미지와 호스트에서 동일할 것으로 예상하는 것은 Docker의 격리 원칙과 호환되지 않는 강력한 요구 사항입니다.

저는 개인적으로 Dockerized 개발 도구에 대한 못생기고 느린 useradd/groupadd 명령으로 이 문제를 해결하고 있습니다. https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/bin-docker/nspire-docker

나는 요점을 완전히 놓치고 있을지도 모릅니다. 그러나 나는 내가 HTTP 사용자가에 / 볼륨과 함께 호스트에서 가능성이 var에 / 로그, 쓰기 권한이 있는지 확인하고자하는 유사한 문제로 어려움을 겪고 있었다 루트 : 루트를 소유자로.

로그 디렉토리가 생성되고 올바른 권한이 있는지 확인하는 진입점을 설정하여 문제를 해결했습니다. 진입점 스크립트가 루트로 실행되기 때문에 이것이 작동한다고 생각합니다.

(삭제된 댓글 -- 잘못된 탭, 죄송합니다)

Docker 외부의 Ubuntu에서 이것을 해킹했습니다. 패키지 bindfs를 설치하고 UID 및 GID를 컨테이너 내부에서 사용되는 것에 매핑하면서 볼륨 내용이 있는 디렉터리를 다른 경로에 바인딩합니다.

sudo bindfs -u UID -g GID 이전 경로 새 경로

그런 다음 newpath를 도커 볼륨으로 사용하십시오. Oldpath는 여전히 호스트에 대해 올바른 소유권을 표시하고 게스트에 대해서는 newpath를 표시합니다.

@jjv 문제는 bindfs가 정말 느리다는 것입니다.

@ cpuguy83 예, 최적과는 거리가 멀지 만 비슷한 상황에있는 누군가를 도울 수 있습니다. 이것은 프로덕션에서 UID와 GID가 호스트와 게스트 간에 여전히 일치해야 하는 동안 개발 가상 머신 내에서 작동하도록 하기 위한 것입니다(vmhgfs는 UID/GID 설정을 허용하지 않음).

성능 저하를 너무 많이 일으키지 않는다는 가정 하에 도커가 이를 구현할 때 일종의 bindfs 기능이 사용된다면 실제로 좋을 것입니다. 그렇게 하면 컨테이너가 올바른 사용자로 실행되고 있는지 확인할 필요가 없습니다. 또한 리터럴 uid/gid 대신 논리적 이름을 사용할 수 있어야 합니다.

@jsternberg 엄청난 성능 히트입니다. vbox 공유 폴더를 사용하는 것과 거의 유사합니다.

+1

로컬 개발 사용 사례의 경우 Docker에 이 기능이 반드시 필요하다고 생각합니다. 그리고 그런 경우 이 기능이 Windows와 OSX를 모두 지원하기를 바랍니다.

Vagrant는 호스트 사용자의 UID/PID를 vagrant 사용자의 UID/PID로 매핑하여 이를 지원하는 것 같습니다. 그러나 개발 목적으로 Vagrant 대신 Docker를 사용하고 싶습니다. 다중 호스트 응용 프로그램을 실행하는 데 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 바인드 마운트는 uid/gid 설정을 지원하지 않습니다.

또한 -v 옵션을 --mount-as 옵션에서 분리하면 -v 옵션이 여러 개 있을 때 혼동이 발생합니다.

이에 대한 좋은 해결 방법은 무엇입니까? 적극적인 개발을 위해 Docker를 사용하고 싶습니다. 어떤 종류의 볼륨을 탑재하지 않는 것은 실제로 옵션이 아닙니다. 코드를 변경할 때마다 다시 빌드해야 하기 때문입니다.

적극적인 개발에 Docker를 사용하려는 이유는 내 프로덕션 환경과 일치하기 위해서입니다.

@berfarah 저는 매일 활발한 개발을 위해 docker를 사용합니다.
파마로 어지럽혀야 하는 경우는 거의 없습니다.
OSX에서 boot2docker를 사용하는 경우 작업 디렉토리가 /Users 내에 있는지 확인하고 문제가 없어야 합니다.

@cpuguy83 빠른 답변 감사합니다. 로그를 작성할 수 없는 레일 환경에 권한 문제가 있으며 권한으로 인해 때때로 실패 지점이 있습니다. 이것은 내 서비스가 파일 중 하나와 다른 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를 위해 stdout/stderr로 이동할 로그가 있습니까?

@cpuguy83 이 문제는 OSX에 영향을 미치지 않습니다. thaJeztah가 2014년 7월 24일에 댓글을

OS X에는 볼륨에 대한 '소유권 무시' 기능이 있습니다. 효과적으로 이것은 모든 사용자가 파일/디렉토리를 소유자인 것처럼 보이게 합니다.

@ncjones는 실제로 OS X에도 동일하게 적용됩니다. 여기서 말하는 "볼륨"은 OS X 자체에서 사용되는 하드 디스크/파티션(볼륨)입니다. Boot2Docker 작업에 차이가 있는지 의심되지만 확실하지 않습니다.

내 의견은 Linux(따라서 Boot2Docker VM 내부)에서 _similar_가 가능한지 알려주기 위한 것입니다.

혼란을 드려 죄송합니다.

@ryneeverett 감사합니다. 도움이 됩니다. 그런 다음 필요한 위치에서 각각 권한을 755에서 775로, 644에서 664로 수정해야 합니까? 편집: 읽기 능력!

@cpuguy83 감사합니다! 그것은 @ryneeverett 의 솔루션보다 더 제한적인 수정처럼 보입니다. 모든 프로젝트로 계속 진행할 수 있는 것이 아니기 때문입니다.

@berfarah 도움이 되셨

+1

이것은 도커를 통한 공유 볼륨에 매우 유용하며 내가 가지고 있는 보안 문제를 해결합니다.

  • 컨테이너 uid 및 gid가 호스트의 권한 있는 루트가 아닌 사용자에게 실수로 매핑되는 공유 볼륨입니다. (예: 호스트의 컨테이너에 의해 생성된 파일은 sudo w/o passwd, 액세스가 제한된 콘텐츠 등을 할 수 있는 사용자에게 매핑됩니다.)

이 문제를 수정하면 Apache 또는 일부 미들웨어와 함께 수많은 컨테이너를 실행하고 로깅 볼륨 및/또는 다양한 콘텐츠/업로드 디렉토리를 공유하는 엔터프라이즈 사용자에게 매우 편리합니다. 또한 개인적으로 Linux에서 최종 사용자 앱(예: syncomm/spotify)을 컨테이너화하는 동안 이러한 권한과 관련하여 몇 가지 골칫거리를 겪었습니다. 오늘날 많은 해결 방법 자체가 문제가 있습니다. 궁극적으로 이것은 docker 내부에서 수정되어야 합니다. 특히 이 문제가 컨테이너의 0:0 uid/gid가 내 호스트의 루트에 매핑되는 방식을 강조할 때 루트 셸 스크립트를 진입점으로 실행하는 것이 편하지 않습니다. 나는 초기 제안 "docker run -v /var/lib/docker:/var/lib/ docker:ro :$user:$group"을 좋아합니다.

@syncomm 나는 정반대의 접근 방식을 취할 것입니다.
Docker는 데이터 소유권에 대해 가정할 수 없습니다.

의견 하단에 강조 표시한 접근 방식은 이러한 실제 파일을 uid/gids를 변경할 수 있는 퓨즈 기반 fs에 자동으로 매핑하는 경우 수행할 수 있으며 이는 상당한 성능 영향을 초래할 것입니다.

그리고 곧 컨테이너의 uid 0은 호스트의 uid 0이 아닐 것입니다... 이는 또한 파일 소유권을 훨씬 더 까다롭게 만듭니다.

#2259의 복제품인가요?

@ cpuguy83 정확한 반대 접근 방식이 무엇을 의미하는지 잘 모르겠지만 피드백에 감사드립니다. 당신이 설명하는 클라우드? 데이터 소유권이 도커에 의해 가정되어서는 안 된다는 데 동의하지만 컨테이너에서 호스트로 일관된 매핑을 제공하면 도커 소비자가 이 데이터를 관리하는 작업이 확실히 훨씬 쉬워집니다.

bindfs 해결 방법과 마찬가지로 퓨즈 래퍼로 만들면 상당한 오버헤드가 발생한다는 데 동의합니다. 그러나 큰 처벌 없이 이 난제에서 벗어날 수 있는 방법이 있어야 합니다. 기본적으로 컨테이너는 올바르게 작동하고(호스트와 별도의 고유한 시스템인 것처럼) 호스트의 디렉토리를 볼륨으로 마운트하면 거기에 있는 POSIX 파일 시스템, 권한 및 모든 것이 (올바르게) 표시됩니다. 불행히도 이는 두 "호스트" 간에 일관된 방식으로 데이터를 공유하는 것을 매우 어렵게 만듭니다. nfs, cifs 등과 같은 것들이 이에 사용되며 uid 및 gid 매핑을 지원합니다. 문제를 해결하는 데 평행선이 있을 수 있다고 생각합니다. 솔직히, 나는 이것이 코드에서 어디에서 일어나고 있는지 파악하고 더 잘 이해하기 위해 리포지토리를 더 파고들 필요가 있습니다.

파일 소유권에 대해 언급한 변경 사항은 언제 삭제되나요? 컨테이너와 호스트에 대해 uid 0이 같지 않으면 실제로 루트 셸 스크립트의 진입점을 만드는 것이 훨씬 더 편안해집니다. 그런 다음 올바른 uid/gid를 환경으로 전달하고 컨테이너 시작 시 adduser를 수행하는 제안된 해결 방법을 수행하기만 하면 됩니다.

@synccomm 불행히도, uid/gid 설정으로 마운트할 수 있는 다른 종류의 파일 시스템으로 래핑하지 않고는 잘 알지 못합니다.

궁극적으로 이것은 UID 및 GID의 완전한 양방향 재매핑을 위한 커널 지원이 필요한 것처럼 보이며 관리하기 쉽지도 않습니다.

성능에 민감하지 않은 시나리오의 경우 FUSE를 사용하여 무언가를 수행할 수 있습니다.

집에 루트 소유 파일이 있기 때문에 개발 사용 사례의 경우 여전히 +1입니다.

내 사용 사례의 경우 도커가 호스트 볼륨을 생성할 때 사용자 지정 uid/gid 및 selinux 레이블을 적용할 수 있다면 충분할 것입니다. 디렉토리가 이미 있는 경우 권한과 레이블만 남겨둡니다. 현재 볼륨 권한을 수정하기 위해 루트로 실행되는 이미지에 대해 별도의 진입점을 사용하여 이 문제를 해결합니다.

@ibukanov uid/gid를 적용할 수 없지만 selinux 레이블이 오고 있습니다.

@cpuguy83 호스트 볼륨 디렉토리를 생성할 때 사용자 지정 uid/gid를 적용할 수 없는 기술적인 이유는 무엇입니까?

@ibukanov 위의 의견을 참조하십시오.

@ cpuguy83 댓글에서 문제가 무엇인지 알 수 없습니다. 내 사용자의 경우 uid/gid를 다시 매핑할 필요가 없습니다. 현재 루트로 실행할 때 컨테이너 내부에서 chown uid:gid /host_volume && chmod 770 /host_volume 할 수 있습니다. /host_volume 뒤에 있는 호스트에 디렉토리를 생성할 때 도커가 자체적으로 수행할 수 있다면 얼마나 좋을까요? 이렇게 하면 컨테이너 루트로 위의 작업을 수행하기 위해 컨테이너에 추가 진입점을 제공하는 해킹이 필요하지 않으며 항상 루트가 아닌 계정을 사용하여 코드를 실행할 수 있습니다.

@ibukanov 아, 그건 다릅니다.
Docker는 의도적으로 호스트 디렉토리를 변경하지 않습니다.
#9092를 수행하면 도커가 dir을 생성하면 이를 일반 볼륨처럼 취급합니다(즉, 컨테이너의 볼륨 경로에 있는 모든 것을 호스트로 복사하고 컨테이너에 있던 것처럼 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 나는 그것이 같은 보트라고 생각하지 않습니다. 이 문제는 컨테이너 내에서 생성된 파일(마운트된 볼륨에 대해)이 sudo 액세스 없이 컨테이너 외부에서 읽을 수 없는 경우입니다. www-data 사용자는 마운트된 파일에 대한 읽기 액세스만 필요하므로 파일에 대해 chmod a+r 수 있습니다.

@ncjones chmod/chown은 컨테이너의 권한에 영향을 미치지 않는 것 같습니다.

나는 이것이 사용하는 동안 여러 지점에서 작동했다고 맹세하기 때문에 너무 혼란 스럽습니다 ...

그렇군요 부럽습니다...

1.3.0rc-1을 작성하도록 업그레이드한 후(아마도) 또는 모든 컨테이너/이미지를 삭제하고 docker-compose up 다시 실행하면 모든 것이 수정된 것 같습니다.... 더 이상 403 forbidden

나는 그것이 어떻게 든 작동한다는 것을 알고 있었기 때문에 ol' rm -rf * 접근 방식을 취했습니다.

이 문제도 어떻게든 해결해야 합니다. 격리해야 하는 무거운 컴파일 작업을 실행하는 데 사용하는 도커 이미지가 있습니다. 따라서 컨테이너는 올라가고 외부 입력을 받고 처리해야 바이너리(출력)가 생성됩니다. 적절한 권한 관리가 없으면 이것을 작동시키는 것이 악몽이었습니다. 내 이미지는 이식 가능해야하므로 호스트에 대해 많은 것을 가정할 수 없습니다.

@alercunha 귀하의 경우 도커 컨테이너 내에서 단일 사용자를 사용하는 것이 좋습니다. 즉 루트로 컴파일하십시오.

@alercunha
Docker 컨테이너가 빌드 출력을 표시하도록 하여 빌드 설정에서 이 문제를 해결했습니다. Dockerfile에는 다음과 같은 내용이 포함됩니다.

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

Docker 호스트 사용자의 실제 uid/gid는 실행 시 컨테이너에 제공될 수 있습니다. 예를 들어 Jenkins 빌드 명령은 다음과 같은 것을 사용합니다.

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

@motin Building as root는 여러 타사 프로젝트를 빌드하기 위해 docker/buildroot를 사용하고 있기 때문에 피하려고 합니다. 아이디어는 내 빌드 환경을 엉망으로 만드는 소스 코드에 대한 보호 기능을 갖는 것입니다. 따라서 루트로 구축하는 것은 좋은 생각이 아닙니다.

@ncjones 감사합니다! 그것은 실제로 좋은 생각이며 내 특정 경우에 솔루션으로 잘 작동할 수 있습니다.

@alercunha 이 경우 각 타사 프로젝트에 대해 별도의 이미지/컨테이너를 사용하는 것이 좋습니다. 예를 들어 각 타사 프로젝트를 빌드하기 위해 공식 도커 이미지를 제출한 경우와 같이 오픈 소스 커뮤니티에 더 나은 혜택을 줄 수도 있습니다.

www-data에 대한 모든 권한을 부여하려면 다음을 사용할 수 있습니다.

RUN usermod -u 1000 www-data

마운트된 볼륨의 도커에서 작업을 실행할 때 문제가 발생했습니다. 결과 파일은 루트가 소유했으며 docker 명령을 실행하는 사용자가 관리할 수 없습니다. 현재 해결 방법은 권한을 수정하기 위해 작업 후 다음을 실행하는 것입니다.

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

docker가 DockerFile의 USER 명령에 지정된 사용자가 소유할 호스트 기반 탑재 볼륨의 권한을 변경하도록 할 수 있습니까? 분명히 권한을 구성할 수 있어야 하지만 기본 동작을 갖도록 할 수 있습니다.

@mig-foxbat
내 목적을 위해 docker가 호스트 디렉토리가 처음 생성될 때 이미지의 마운트 지점에서 호스트 디렉토리에 대한 소유권과 권한을 설정하기만 하면 충분할 것입니다. 호스트 디렉토리가 이미 존재하는 경우 도커는 그대로 둘 수 있습니다.

@mig-foxbat & @ibukanov 이 문제를 열 ​​때 나를 위한 필수 전제 조건은 호스트 파일 시스템에 대한 권한이 변경 되지 않는다는 것입니다(예: _NFS_로 할 수 있는 것과 유사한 컨테이너 매핑에 가상이 있음).

현재 수행하려는 작업은 컨테이너 내의 일부 시작 스크립트에서 _chown_을 실행하여 쉽게 수행할 수 있습니다.

곧 출시될 볼륨 플러그인 아키텍처가 마음에 들지만 Docker 팀에서 이 기능을 추가하는 것이 훨씬 좋습니다. Docker는 컨테이너에서 루트가 아닌 사용자와 함께 볼륨을 사용할 때까지 잘 작동합니다. 그런 다음 작업(예: 로깅)이 작동하지 않으면 스타벅스 창을 통해 랩톱을 던지거나 위에서 참조한 stackoverflow 항목을 찾습니다.

+1 이 문제로 인해 복잡해지는 루트가 아닌 사용자로 애플리케이션을 실행하는 컨테이너를 갖고 싶습니다.

LXC의 id_map 기능을 사용하여 이 기능을 구현하지 않는 이유는 무엇입니까?

방금 @thaJeztah가 위에서 언급한 "id_map"(일명 사용자 네임스페이스 지원)에 대한 답변을 확인했습니다.

권한을 설정하는 데 약간의 추가 작업이 필요하지만 수십 개의 컨테이너를 루트가 아닌 상태로 실행하고 권한 문제를 피하고 있습니다. 대부분의 데이터 컨테이너는 다음과 같이 시작합니다.
ENV CONTAINER_USER 영사
환경 컨테이너_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에 포함되어 있으면 무슨 일이 일어나고 있는지 좀 더 간단합니다.

이제 일종의 매핑을 사용하여 컨테이너의 호스트 파일에 액세스하려는 위의 참고 사항이 있습니다. 나는 이것이 확실히 위험한 제안이라고 생각합니다. 종종 직접 호스트 매핑 없이 파일을 공유하려고 하는 것이 가장 좋은 솔루션일 것입니다. 그렇지 않으면 도커 보안이 다소 역전되기 때문입니다. 그렇지 않은 경우보다 적은 권한을 가진 컨테이너가 아니라 호스트 파일에 대한 루트 수준 액세스(종종 사용 사례로 추정됨)가 있는 루트가 아닌 컨테이너로 실행되는 것에 대해 이야기하고 있습니다. 대부분의 상황에서 그룹 권한 또는 기타 솔루션이 우선해야 한다고 생각합니다.

마운트된 디렉토리를 검색하고 su를 통해 하위 명령을 실행하는 진입점 셸 스크립트로 이 문제를 해결했습니다.

/data 디렉토리가 호스트의 볼륨으로 마운트되는 solr 컨테이너의 예:

#!/bin/bash

chown -R $SOLR_USER:$SOLR_USER /data

su -c "$@" -m $SOLR_USER

_USER POLL_

_이 토론에 변경 사항이 있을 때 알림을 받는 가장 좋은 방법은 오른쪽 상단의 구독 버튼을 클릭하는 것입니다._

아래 나열된 사람들은 무작위 +1로 귀하의 의미 있는 토론에 감사했습니다.

@jcercurati
@iangelov
@scue
@razvanphp
@귀신
@andrerocker
@anandnalya
@ddopson
@hason
@하딤
@iyn
@cgrantcharovtp
@sandytrinh
@고멕스
@DrBenton
@tehmaspc
@segphault
@avaz
@에다비즘
@야요
@스타니슬라브
@smebberson
@tony-kerz
@msierks
@pdonorio
@samsung8610
@qm78
@joshughes
@roelvanduijnhoven
@블라디미르브라이트
@ava-dylang

이 스레드에서 말하는 것은 자동으로 사용자를 구독하므로 예, 의도적으로 추가로 구독을 취소하지 않는 한 모든 사람들이 구독됩니다. (또한 your 로 언급하는 _누구_인지 확실하지 않음)

이것은 확실히 필수입니다. Docker는 UID를 올바르게 다시 매핑해야 합니다. 그렇지 않으면 컨테이너에서 호스트 OS 볼륨으로 생성된 모든 것은 루트가 소유합니다. 해결 방법은 끔찍합니다. 컨테이너 내부의 사용자를 변경하면 모든 종류의 합병증이 발생하고 모든 곳에서 씹어야 하고 Dockerfile이 추악해지면서 커집니다. 그리고 최악의 하드코딩 UID는 컨테이너를 이식할 수 없게 만듭니다!

+1 이 기능은 파일에서 사용자 ID를 덮어쓰는 것을 피하기 위해 도커 컨테이너와 호스트 시스템 간의 전환을 피하고 싶기 때문에 높이 평가될 것입니다.

UID 사용자 정의를 얻는 것은 현재 가능하지만 다음 제약 조건 내에서 가능합니다.

  • 컨테이너가 환경 변수를 통해 필요한 uid를 수락하도록 하여 Uid 사용자 정의가 가능합니다. 이렇게 하면 호스트가 컨테이너가 사용하는 uid를 완전히 제어할 수 있으며 추가 이점이 있습니다. 여러 변수를 동일한 uid 값으로 설정할 수 있습니다. 매핑이 1:1이어야 하므로 Uid 재매핑은 단일 호스트 uid에 대한 여러 컨테이너 uid 매핑을 지원할 수 없습니다. 예를 들어, 원하는 매핑이 실제로 응용 프로그램이 uid=0으로 실행되어야 하는 경우 변수를 주입하여 수행할 수 있지만 uid 재매핑을 통해서는 할 수 없습니다. 위의 @ncjones@mitchcapper 솔루션을 참조하십시오.
  • 그러나 루트 uid=0은 다시 매핑하는 경우를 제외하고는 다른 값으로 변경할 수 없습니다: #12648.

거의 모든 최신 웹 개발 프레임워크에는 프로젝트 구성에 정의되고 탑재된 볼륨을 통해 공유되는 프로젝트 내부에 로그 폴더와 캐시 폴더가 있습니다. vboxfs를 먼저 사용했지만 너무 느렸습니다. NFS 마운트를 생성하기 위해 docker-machine-nfs 를 찾았고 속도가 빠르지만 이제 컨테이너의 웹 파일은 502:dialout이 소유하고 chmod 또는 chown이 될 수 없으므로 웹 앱이 실행되지 않습니다. docker vagrant box를 시도했지만 모든 다른 환경 변수 및 구성에 vagrant가 필요하며 아직 docker-machine에서는 작동하지 않습니다. 단기적인 수동 프로세스일지라도 www-data 또는 기타 항목에 사용자 502를 추가하는 해결 방법이 있습니까? 그게 내가 사업을 하는 데 필요한 전부야!

+1

이것을 따르는 사람들을 위해; 현재 바인드 마운트 파일의 소유권을 재귀적으로 변경하는 실험적 기능에 대한 PR이 있습니다. 하지만 이 기능은 호스트의 파일을 변경하므로 주의해서 사용해야 합니다(모든 경우에 원하는 것이 아닐 수 있음). https://github.com/docker/docker/pull/14632 (및 https://github.com/docker/docker/pull/16767) 참조

+1

그건 그렇고, 나는 ACL을 사용하여이 문제를 해결했습니다.

@kvaps , 자세히 설명하시겠습니까?

@posita , 내 내기는 @kvapsPOSIX ACL 에 대해 이야기하고 있다는 것 입니다. 내가 옳다면 그것은 OP 요청과 동일하지 않습니다.

@posita , @denydias , 답변이 길어 죄송합니다. 예, 나는 이것에 대해 이야기하고 있습니다.
owncloud, samba 및 minidlna와 같은 많은 컨테이너가 있습니다. 모두 다른 uid와 gid로 작업합니다.
그들은 모두 동일한 파일로 작동합니다. 모든 사람이 파일을 읽고 쓸 수 있는 것은 무엇입니까? acl 옵션을 사용하여 파일 시스템을 호스트 시스템에 마운트하고 chown 명령과 같이 간단하게 이 파일에 대한 uid 및 gid 권한을 모든 사람에게 부여했습니다.

# 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 인수를 사용하여 이 문제를 해결했습니다. 컨테이너를 만든 후 특별한 작업을 수행할 필요가 없으므로 공유할 생각입니다. (도커 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 usernameusername 의 사용자 ID를 변경하고 username 의 HOME에 있는 파일의 소유권 변경을 트리거하지만 이전에 소유했던 모든 파일 username HOME 외부의

@riquito Dockerfile 에서 생성된 전용 사용자와 함께 사용합니다.

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

따라서 이전에 username 소유한 파일이 없습니다. 그래서 문제가 없다고 생각합니다 ;)

참고로 setfacl 는 OS X로 다시 추적되는 볼륨에서 작동하지 _not_ 합니다.

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 는 Docker 머신 및 Boot2Docker를 통해 OS X에서 호스팅됩니다. boot2docker/boot2docker#581도 참조하십시오.)

@posita virtualbox를 사용하여 boottodocker 이미지를 호스팅하고 있습니까? 그렇다면 실제로 virtualbox가 공유 폴더를 수행하는 방식에 제한이 있을 수 있습니다. 가상 상자 공유 폴더를 통해 어떤 종류의 규칙적인 투과성을 수행하는 데 많은 어려움을 겪었습니다.

@ava-dylang, 좋은 지적입니다. 위의 내용은 Parallels의 기본 공유 폴더 구현을 사용하는 Parallels 드라이버 가 포함된 Docker Machine을 통해 이루어지며 비슷하게 제한됩니다. (이러한 유형의 환경에 대한 제안에 대해서는 https://github.com/docker/machine/issues/13#issuecomment-164320881도 참조하십시오.)

FWIW, 내 유틸리티 Scuba 에서 파일 소유권에 문제가 있었습니다.

호스트에서 호출하는 사용자와 동일한 UID/GID를 가진 사용자를 컨테이너에 생성하는 "초기화" 스크립트를 추가하여 문제를 해결했습니다. JonathonReinhart/scuba#11 및 JonathonReinhart/scuba#13을 참조하십시오.

이제 컨테이너에서 생성된 파일은 호스트에서 생성된 것과 똑같이 보입니다.

_업데이트:_ 문제가 발생했습니다(JonathonReinhart/scuba#22). 대신 호스트 사용자의 uid/gid를 기반으로 내 자신의 /etc/passwd 및 친구를 생성하여 수정하고 컨테이너에 주입했습니다(JonathonReinhart/scuba#24 참조).

+1

호스트가 다중 테넌트 모드에서 실행될 때 유지 관리 및 보안을 강화합니다.

호스트에서 볼륨이 있는 컨테이너로 전체 Wordpress를 공유할 때 Wordpress 설치에 권한 문제가 있었습니다.

내 스택에는 기본 이미지가 있습니다. 기본 이미지는 기본 수정 사항이 있는 데비안이며 다른 모든 이미지는 이 이미지에서 빌드됩니다.

기본 이미지에는 다음 부분이 있습니다.

### 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(대부분의 기본 Linux 첫 번째 비루트 사용자의 UID/GID는 500 또는 1000)인 경우 이 스크립트는 www-data 사용자의 UID/GID를 33에서 500으로 변경합니다. 호스트에서 무엇이든 공유하면 Docker는 www-data 사용자가 소유한 파일과 폴더를 생각합니다!

PHP-FPM 설정 파일에서 사용자와 그룹도 www-data 합니다.

nginx Dockerfile에서 다음도 설정해야 합니다.

# 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. 더 중요한 것은, 전체 Wordpress 설치에 대한 세계 쓰기 가능( 0777) 액세스 권한을 부여하는 것은 매우 위험하며 공식 WP 문서에서 명시적으로 반대하는 것이 좋습니다. 게다가 이 모든 것이 호스트에서 마운트되어 인터넷에서 임의의 업로드가 _host_ 파일 시스템에 쓸 수 있도록 허용했습니다.

@jantman 죄송합니다. 첫 번째 해킹으로 권한 문제도 해결된 것 같습니다. 기본 권한을 변경할 필요가 없습니다.

분명히 모든 사람은 호스트 사용자 UID:GID 를 찾아 이에 따라 구성을 변경해야 합니다. 또한 퀘스트에서 이미 존재하거나 새로운 사용자와 연결하십시오. 광산은 리빙 스택의 실제 사례입니다.

docker가 이 문제에 대한 솔루션을 제공하지 않을 때까지 가정은 유지됩니다.

내 솔루션은 @JonathonReinhart 또는 @pa-de-solminihac 솔루션과 동일합니다.

로컬 볼륨을 생성하여 이 작업을 수행할 수 있으며 방금 마스터 https://github.com/docker/docker/pull/20262에 도착했습니다

이것을 고정으로 닫습니다.

안녕 나는 또한 내 dockerfile에서 해결 방법을 만들어야했습니다.

...
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를 사용하지 않습니다. 실제로 바인드 마운트가 uid 옵션을 지원하지 않기 때문에 기존 FS _any_의 하위 디렉토리를 사용할 수 없습니다. 로컬 볼륨이 무엇인지 모르겠습니다. FS를 직접 생성하고 마운트한 다음 일반 호스트 볼륨( -v my-created-fs:container-mount-point )을 사용할 수 있습니다.

이 스레드에 꽤 늦었지만 이 문제가 해결되었습니까? 여기에 언급된 모든 다양한 문제에서 100% 명확하지 않습니다. @brthor 는 내가 볼 수 있는 최고의 솔루션을 가지고 있는 것 같지만

나에게 UID와 GID를 하드 코딩하는 것은 환경 간의 이식성에 대한 나쁜 생각이며 컨테이너를 부팅하거나 이미지를 빌드할 때마다 명령줄 인수를 추가할 필요가 없다고 생각합니다. 도커파일. Dockerfile 또는 docker-compose.yml을 통해 "호스트의 uid 매핑" 옵션을 지정할 수 있는 간단한 옵션이 없을 수 있습니까?

이미 좋은 솔루션이 있을 수 있지만 문서나 이 스레드에서 실제로 이를 파악할 수 없습니다.

@alvinchevolleaux 에게 감사드립니다. 위의 https://github.com/dotnet/cli 용 CI에 게시한 솔루션을 몇 달 동안 성공적으로 사용하고 있음을 확인할 수 있습니다.

그것을 추천하십시오!

@brthor 예, 제가 사용했던 것입니다. export USER_ID=$(id -u) 를 .bash_profile에 추가하여 다양한 환경에서 모두 자동으로 설정되었습니다. 감사합니다.

위에서 설명한 것처럼 홈 폴더의 콘텐츠를 컨테이너로 공유할 때 동일한 UID를 가진 사용자 계정을 추가하십시오. 여기에 UID가 1000이 아닌 경우 대처할 수 있는 트릭이 있습니다. 각 사용자가 Dockerfile에서 자신의 도커 이미지를 빌드한다고 가정합니다.

Dockerfile 에는 다음이 포함되어야 합니다.

RUN useradd --uid 1000 -m vagrant
USER vagrant

1000 상수는 _git filter_를 사용하여 실제 UID로 대체됩니다. 호스트에서 다음을 실행합니다.

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

이것은 파일을 _smudging_하여 Dockerfile을 체크아웃할 때 1000 를 실제 UID로 대체하여 작동합니다. Git은 커밋할 때 파일을 _clean_합니다( 1000 되돌리기). 컨테이너에서 실행되는 모든 명령은 올바른 UID를 가진 vagrant 사용자로 실행됩니다.

여기에 제공된 모든 솔루션은 해결 방법일 뿐이므로 이 티켓을 다시 열어야 합니다.
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 옵션이 무엇인지 알려주는 문서를 찾을 수 없습니다. 그래서 나는 이것이 어떻게 작동하는지에 대해 정말로 추측하고 있습니다.

이 문제를 다시 열어주세요. 새 로컬 드라이버는 선택된 사용자 ID로 로컬 호스트 디렉토리를 마운트하는 문제를 전혀 해결하지 못하는 것 같습니다.

@calavera
로컬 호스트 볼륨을 사용하여 루트로 삭제되는 파일 문제를 해결할 수 있는 방법에 대해 말씀해 주시겠습니까? 특히 CI 시나리오에 도커를 사용할 때 이 문제가 자주 발생하는 것을 보았습니다.

링크된 PR을 보면 바로 눈에 띄는 것은 없지만 뭔가 놓치고 있는 것이 확실합니다 😄

docbill/docker-force 와 같은 컨테이너에서 이 해결 방법의 변형을 사용하고 있습니다. 그러나 나에게 더 깨끗한 솔루션은 스쿼시 루트만 담당하는 컨테이너입니다...

로컬에 bindfs와 같은 것을 사용하면 도움이 될 것입니다. -o map=$(id -u)/root:@$(id -g)/ @root (사용자 네임스페이스가 없다고 가정)를 사용하여 실행할 수 있으며 파일이 소유된 동안 컨테이너 외부에서 파일을 볼 수 있어야 합니다. 그 안에 뿌리.

@ktosiek 감사합니다. 가능성이 있는 것 같습니다. 완전한 예제 docker run 명령 또는 콘솔 세션을 게시할 수 있습니까?

누군가 이 문제에 대한 상태 업데이트를 게시할 수 있습니까? "수정되지 않음"으로 종료되었거나 실제로 구현되었습니까? 쓰레드가 꽤 긴데 해상도가 얼만지 한 눈에 잘 안 보이니 양해 부탁드립니다.

@quinncomendant 참조 https://github.com/docker/docker/issues/7198#issuecomment -191990887
작동하지 않으면 보고합니다.

@LK4D4 감사합니다.

요약하자면, 이 문제는 local 볼륨 드라이버에 대한 마운트 옵션을 허용하는 수정 사항으로 해결 되었습니다.

내가 말할 수 있는 한, 볼륨으로 마운트된 _host-directory의 user: group_을 설정하는 옵션은 없습니다.

@quinncomendant 맞습니다. 호스트 디렉토리를 바인드 마운트할 때 컨테이너가 권한을 포함하여 있는 그대로의 파일을 사용하기를 원합니다. 이러한 권한을 변경하려면 바인드 마운트하기 전에 호스트에서 변경해야 합니다.

@quinncomendant 또는
제공된 솔루션은 실제로 문제를 해결하기 위해 아무 것도 하지 않습니다.
보고되었으며 해당 문제를 해결할 계획도 없습니다.

2016년 7월 6일 17:20, Sebastiaan van Stijn [email protected]
썼다:

@quinncomendant https://github.com/quinncomendant 맞습니다. 언제
컨테이너가 파일을 사용하기를 원하는 호스트 디렉토리를 바인드 마운트
권한이 포함된 있는 그대로 있습니다. 변경하려는 경우
권한을 바인드 마운트하기 전에 호스트에서 수행해야 합니다.


당신이 댓글을 달았기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/docker/docker/issues/7198#issuecomment -230909967 또는 음소거
스레드
https://github.com/notifications/unsubscribe/ADBcWLihVjI1FoSMLKu7DyhwFOpGX0KKks5qTBwMgaJpZM4CQMjR
.

이것은 WON'T FIX 문제인 것 같습니다. 컨테이너화의 _development_ 측면이 계속 간과되고 여전히 해킹을 작성해야 하는 것처럼 보입니다.

내가 지원하는 개발자가 컨테이너 내부에서 호스트 탑재 볼륨으로 명령을 생성하는 프로젝트 파일을 실행하기 때문에 특히 이 문제가 발생했습니다(호스트에 이러한 도구를 설치하면 컨테이너 사용 목적이 완전히 무효화됩니다. 맞죠?).

그들은 이 파일을 빠르게 반복하기를 원하지만 이 스레드의 다른 사람들이 지적했듯이 컨테이너가 실행되는 uid/gid로 기록되므로 추가 조작을 위해 호스트에서 올바르게 chown해야 합니다. 예를 들어 IDE).

이러한 종류의 경우 임시 uid/gid를 shim하는 _docker 특정_ 방법이 필요합니다.

@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) )의 잠재적인 문제는 컨테이너에 해당 uid/gid에 대한 /etc/passwd 또는 /etc/group 항목이 없다는 것입니다. 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 예, 새로운 사용자 이름 공간 기능으로 이 문제를 해결할 수 있다고 생각하지만 말씀하신 대로 컨테이너별로 구현해야 합니다. 최종 결과는 다음과 같습니다. 컨테이너가 "루트"라고 생각하는 대로 실행되지만 실제로는 docker run 명령줄에서 전달된 UID/GID입니다. 그러면 해당 사용자가 소유한 컨테이너에서 파일이 "나옵니다".

@lazyuser @xiaods @JonathonReinhart 문제 설명 아래에 있는 +1 버튼을 클릭해야 합니다.

또는 알림만 받고 싶다면 오른쪽에 있는 구독을 클릭하세요...

@JonathonReinhart : 확실히, 나는 문서를 다시 살펴보았지만 불행히도 컨테이너당 대신 데몬 전체에 매핑을 사용하는 것은 제한 때문에 의식적인 결정이었습니다.

참고: 현재로서는 Docker가 엔진 인스턴스에서 실행되는 모든 컨테이너에서 로컬 캐시의 이미지 계층을 공유하기 때문에 데몬당 단일 매핑 제한이 적용됩니다. 동일한 레이어 콘텐츠를 공유하는 모든 컨테이너에 대해 파일 소유권이 동일해야 하므로 콘텐츠가 다운로드되면 컨테이너 실행에 지연이 없도록 도커 풀의 파일 소유권을 데몬의 사용자 및 그룹 매핑에 매핑하기로 결정했습니다. 이 디자인은 사용자 네임스페이스가 비활성화된 상태에서 사용자가 기대하는 것과 동일한 도커 풀, 도커 푸시 및 컨테이너 시작 성능을 유지합니다.

_(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 버그에 대한 해결 방법이었고, 이번에는 상황을 아이러니하게 표현하지 않을 수 없었습니다.

inotifywait 를 사용하여 이 문제를 해결했습니다. docker 이미지 내에서 실행하려면 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 폴더와 동일한 사용자 및 그룹으로 변경합니다. 호스트 사용자/그룹이 컨테이너에 없는 경우를 대비하여 둘 다의 정수 표현을 사용했습니다. 컨테이너 내부에서는 모든 것이 루트로 실행되기 때문에 누가 그것을 소유하고 있는지는 중요하지 않습니다. 컨테이너 외부에서 호스트 파일 시스템은 /mount에 마운트된 디렉토리와 동일한 소유권을 보여줍니다.

기존 파일 및 디렉토리의 소유권을 유지하기 위해 의도적으로 새로 생성된 파일 및 디렉토리의 소유권만 설정하도록 설계했습니다. 파일 시스템이 마운트될 때마다 chown -R 문으로 모든 것을 날려버리는 것보다 안전합니다. 프로젝트에 균일한 권한이 적용되고 보다 효율적으로 실행되는 더 간단한 솔루션을 원하는 경우 inotify-hookable 을 살펴

경고: 하위 디렉토리당 하나의 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의 소유라고 가정합니다 brian:www-data 가 소유하게 됩니다

이 예제를 기반으로 www-data:www-data가 소유한 호스트 디렉토리 /var/www/html/upload가 있다고 가정해 보겠습니다 brian:www-data의 소유임을 명심하십시오 www-data:www-data가 아니라 brian:www-data 가 소유 합니다. Brian:www-data 소유

TL;DR: 마운트된 호스트 디렉토리를 user:group 에 chown하여 사용하려는 user:group 을 전달합니다 .

@briansrepo 설명 감사합니다. 모두 이해가 되지만 RUN 내부에서 이것이 어떻게 작동하는지 이해하지 못합니다. 컨테이너가 실행될 때 백그라운드에서 실행해야 한다고 생각합니다(예: docker run ).

@btiernay 저도 이 아이디어가 좋습니다.
@briansrepo 는 적어도 컨테이너에서 발생하는 일을 다룹니다.
빌드 프로세스는 여전히 다음과 같이 해결할 수 있습니다.

RUN usermod -u 1000 www-data

이것은 여전히 ​​해결 방법입니다.

내 LEMP 스택에는 기본 Dockerfile에 다음 Nginx 사전 구성이 있습니다.

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

이것은 uid, gid 500 및 nginx를 가져오는 호스트 ssh 세션에서 새로 생성된 모든 파일이 결국 해당 파일에 액세스할 수 없는 해킹입니다(ID가 500인 사용자 또는 그룹이 컨테이너에 없었기 때문에). ssh 세션에서 호스트의 공유 볼륨으로 새 파일을 복사하고 나중에 이 컨테이너에 docker exec 를 복사할 때 www-data 사용자에 대해 생성해야 하는 uid, gid 번호를 확인할 수 있습니다. uid, gid 파일을 보고 있습니다.

내가 찾은 문제는 호스트 시스템의 공유 폴더에 새 파일을 복사한 경우(DigitalOcean의 CoreOS 인스턴스와 같이 ssh 세션으로 액세스한 경우) Nginx가 새로 생성된 파일에 액세스할 수 없다는 것입니다. 따라서 권한과의 절대적인 호환성을 원하면 컨테이너 생성 시 웹 서버 파일을 Docker 컨테이너에 공유해야 합니다(적어도 1년 전 공유 볼륨에서 이러한 uid, gid 문제가 발생했을 때) .

또는 nginx 컨테이너와 파일을 공유하는 도커 컨테이너에 ssh 서비스를 설치할 수도 있습니다. 이렇게 하면 파일을 복사/수정하면 올바른 uid, gid를 갖게 됩니다. 그러나 이것은 ssh 세션 대신 docker inspect 를 사용해야 하는 Docker 모범 사례에 대한 것입니다. "Docker는 VM이 ​​아닙니다"(너무 쉬운 솔루션이겠죠?).

내 생각에 Docker 컨테이너는 서비스 또는 실행 파일처럼 작동해야 하며 원하지 않는 경우 내 웹 서버 파일을 인질로 잡아서는 안 됩니다. 데이터베이스는 (때때로) 다른 종류의 것이지만, 모든 정적, 웹서버, 데이터베이스 파일이 컨테이너 외부에 있는 동일한 성배 컨테이너 인프라를 달성하는 것이 왜 불가능한지 모르겠습니다(그러나 컨테이너는 수정(예: 삭제, 생성, 수정)하고 호스트의 권한 문제 없이 수정할 수도 있습니다.

docker volume create --opt 하면 uid, gid를 정의할 수 있지만 docker-compose 에는 해당되지 않습니다. https://github.com/docker/compose/issues/3715

우리는 uid/gid를 매핑하기 위한 크로스 플랫폼 go-to(gosu 아님) 솔루션이 정말로 필요합니다. 이 문제만으로도 초보자가 도커를 인식하는 방식에 막대한 피해를 입힙니다.

빌드 시 설정된 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 또는 시작 스크립트의 일부로 실행할 수 있습니다. setuid 비트 가 있는 root 소유의 바이너리로 컨테이너에 설치되고 권한을 에스컬레이션하여 적절하게 변경합니다. 개발 컨테이너에서만 사용해야 합니다.

이것이 유용하다고 판명되면 Docker 엔진은 docker run 플래그를 통해 일부 또는 모든 논리를 통합할 수 있습니다.

docker volume 를 사용하여 해결했습니다.

@hashar 어떻게? 예를 들어 줄 수 있습니까?

따라서 gosu 및 진입점 스크립트를 사용하는 것 외에는 여전히 이에 대한 해결책이 없습니까?

현재로서는 Docker 팀이 이에 대한 공식 업데이트를 할 때까지 이에 대한 해결 방법으로 2가지 옵션이 있는 것 같습니다.

이것이 여전히 문제라는 것이 너무 부끄럽습니다. 이론적으로 userns-remap이 있지만 사용자 친화적이지 않습니다.

이 페이지가 도움이 되었나요?
0 / 5 - 0 등급