Docker 및 --userns-remap, 호스트와 컨테이너간에 데이터를 공유하기 위해 볼륨 권한을 관리하는 방법은 무엇입니까?
Docker에서 컨테이너 내부에서 생성 된 파일은 호스트에서 검사하는 동안 예측할 수없는 소유권을 갖는 경향이 있습니다. 볼륨에있는 파일의 소유자는 기본적으로 루트 (uid 0)이지만 루트가 아닌 사용자 계정이 컨테이너에 관여하고 파일 시스템에 쓰는 즉시 소유자는 호스트 관점에서 다소 무작위가됩니다.
docker 명령을 호출하는 동일한 사용자 계정을 사용하여 호스트에서 볼륨 데이터에 액세스해야하는 경우 문제가됩니다.
일반적인 해결 방법은 다음과 같습니다.
- Dockerfiles (이식 불가능)에서 생성시 사용자 uID 강제
- 호스트 사용자의 UID를
docker run
환경 변수로 명령에 전달한 다음chown
진입 점 스크립트의 볼륨에서 일부 명령 을 실행 합니다.
두 솔루션 모두 컨테이너 외부의 실제 권한을 제어 할 수 있습니다.
사용자 네임 스페이스가이 문제에 대한 최종 해결책이 될 것으로 예상했습니다. 최근에 출시 된 버전 1.10 및 --userns-remap을 내 데스크톱 계정으로 설정하여 몇 가지 테스트를 실행했습니다. 그러나 마운트 된 볼륨에 대한 파일 소유권을 더 쉽게 처리 할 수 있을지 확신 할 수 없으며 실제로 그 반대 일 수 있습니다.
이 기본 컨테이너를 시작한다고 가정 해 보겠습니다.
docker run -ti -v /data debian:jessie /bin/bash
echo 'hello' > /data/test.txt
exit
그런 다음 호스트의 콘텐츠를 검사합니다.
ls -lh /var/lib/docker/100000.100000/volumes/<some-id>/_data/
-rw-r--r-- 1 100000 100000 6 Feb 8 19:43 test.txt
이 숫자 '100000'은 내 호스트 사용자의 하위 UID이지만 내 사용자의 UID와 일치하지 않기 때문에 권한없이 test.txt를 편집 할 수 없습니다. 이 하위 사용자는 docker 외부의 실제 일반 사용자와 친화력이없는 것 같습니다. 다시 매핑되지 않았습니다.
호스트와 컨테이너 간의 UID 정렬로 구성된이 게시물의 앞부분에서 언급 한 해결 방법 UID->sub-UID
은 네임 스페이스에서 발생 하는 매핑 으로 인해 더 이상 작동하지 않습니다 .
그렇다면 사용자 네임 스페이스가 활성화 된 상태에서 (보안 향상을 위해) docker를 실행하는 방법이 있습니까?
사용자와 그룹을 미리 정렬 할 수있는 경우 호스트 사용자가 컨테이너 내부의 네임 스페이스 사용자에 해당하도록 특정 방식으로 UID 및 GID를 할당 할 수 있습니다.
다음은 예입니다 (Ubuntu 14.04, Docker 1.10).
고정 된 숫자 ID로 일부 사용자를 만듭니다.
useradd -u 5000 ns1 groupadd -g 500000 ns1-root groupadd -g 501000 ns1-user1 useradd -u 500000 -g ns1-root ns1-root useradd -u 501000 -g ns1-user1 ns1-user1 -m
/etc/subuid
및/etc/subgid
파일 에서 자동 생성 된 하위 ID 범위를 수동으로 편집 합니다.ns1:500000:65536
(주 더 레코드가없는
ns1-root
및ns1-user1
인한MAX_UID
및MAX_GID
한계에/etc/login.defs
)에서 사용자 네임 스페이스 활성화
/etc/default/docker
:DOCKER_OPTS="--userns-remap=ns1"
데몬을 다시 시작
service docker restart
하고/var/lib/docker/500000.500000
디렉토리가 생성 되었는지 확인 합니다.이제 컨테이너 내부에는
root
및user1
, 호스트에ns1-root
및ns1-user1
, 일치하는 ID가 있습니다.업데이트 : 루트가 아닌 사용자가 컨테이너 (예 : user1 1000 : 1000)에 고정 ID를 갖도록 보장하려면 이미지 빌드 중에 명시 적으로 생성합니다.
테스트 드라이브:
볼륨 디렉터리 준비
mkdir /vol1 chown ns1-root:ns1-root /vol1
컨테이너에서 시도
docker run --rm -ti -v /vol1:/vol1 busybox sh echo "Hello from container" > /vol1/file exit
호스트에서 시도
passwd ns1-root login ns1-root cat /vol1/file echo "can write" >> /vol1/file
휴대용이 아니며 해킹처럼 보이지만 작동합니다.
docker cp
명령 을 사용하여 권한 문제를 방지 할 수 있습니다 .
소유권은 대상의 사용자 및 기본 그룹으로 설정됩니다. 예를 들어 컨테이너에 복사 된 파일
UID:GID
은 루트 사용자 로 만들어집니다 . 로컬 시스템에 복사 된 파일UID:GID
은docker cp
명령 을 호출 한 사용자의로 생성됩니다 .
다음은 사용하도록 전환 한 예입니다 docker cp
.
$ docker run -ti -v /data debian:jessie /bin/bash
root@e33bb735a70f:/# echo 'hello' > /data/test.txt
root@e33bb735a70f:/# exit
exit
$ docker volume ls
DRIVER VOLUME NAME
local f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93
$ sudo ls -l /var/lib/docker/100000.100000/volumes/f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93/_data
total 4
-rw-r--r-- 1 100000 100000 6 Oct 6 10:34 test.txt
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e33bb735a70f debian:jessie "/bin/bash" About a minute ago Exited (0) About a minute ago determined_hypatia
$ docker cp determined_hypatia:/data/test.txt .
$ ls -l test.txt
-rw-r--r-- 1 don don 6 Oct 6 10:34 test.txt
$ cat test.txt
hello
$
그러나 컨테이너에서 파일을 읽으려는 경우에는 명명 된 볼륨이 필요하지 않습니다. 이 예에서는 명명 된 볼륨 대신 명명 된 컨테이너를 사용합니다.
$ docker run -ti --name sandbox1 debian:jessie /bin/bash
root@93d098233cf3:/# echo 'howdy' > /tmp/test.txt
root@93d098233cf3:/# exit
exit
$ docker cp sandbox1:/tmp/test.txt .
$ ls -l test.txt
-rw-r--r-- 1 don don 6 Oct 6 10:52 test.txt
$ cat test.txt
howdy
$
이 질문에 설명 된대로 파일을 컨테이너에 복사하려는 경우 명명 된 볼륨이 유용하다는 것을 알았습니다 .
한 가지 해결 방법은 호스트와 일치하도록 빌드시 사용자의 uid를 동적으로 할당하는 것입니다.
예 Dockerfile
:
FROM ubuntu
# Defines argument which can be passed during build time.
ARG UID=1000
# Create a user with given UID.
RUN useradd -d /home/ubuntu -ms /bin/bash -g root -G sudo -u $UID ubuntu
# Switch to ubuntu user by default.
USER ubuntu
# Check the current uid of the user.
RUN id
# ...
그런 다음 다음과 같이 빌드하십시오.
docker build --build-arg UID=$UID -t mycontainer .
다음으로 실행 :
docker run mycontainer
If you've existing container, create a wrapper container with the following Dockerfile
:
FROM someexistingcontainer
ARG UID=1000
USER root
# This assumes you've the existing user ubuntu.
RUN usermod -u $UID ubuntu
USER ubuntu
This can be wrapped in docker-compose.yml
like:
version: '3.4'
services:
myservice:
command: id
image: myservice
build:
context: .
volumes:
- /data:/data:rw
Then build and run as:
docker-compose build --build-arg UID=$UID myservice; docker-compose run myservice
'Development Tip' 카테고리의 다른 글
ElasticSearch 다단계 부모-자식 집계 (0) | 2020.10.10 |
---|---|
블루투스 핸즈프리 클라이언트 볼륨 제어 (0) | 2020.10.10 |
Java 문자열에서 인쇄 할 수없는 모든 문자를 제거하는 가장 빠른 방법 (0) | 2020.10.10 |
2012 년 6 월 12 일부터 내 웹 사이트에서 요청한 URL의 1 %에 "정의되지 않음"이 무작위로 추가됨 (0) | 2020.10.10 |
서버에서 보낸 이벤트와 PHP-서버에서 이벤트를 트리거하는 것은 무엇입니까? (0) | 2020.10.10 |