Development Tip

Docker 및 --userns-remap, 호스트와 컨테이너간에 데이터를 공유하기 위해 볼륨 권한을 관리하는 방법은 무엇입니까?

yourdevel 2020. 10. 10. 12:08
반응형

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

  1. 고정 된 숫자 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
    
  2. /etc/subuid/etc/subgid파일 에서 자동 생성 된 하위 ID 범위를 수동으로 편집 합니다.

    ns1:500000:65536
    

    (주 더 레코드가없는 ns1-rootns1-user1인한 MAX_UIDMAX_GID한계에 /etc/login.defs)

  3. 에서 사용자 네임 스페이스 활성화 /etc/default/docker:

    DOCKER_OPTS="--userns-remap=ns1"
    

    데몬을 다시 시작 service docker restart하고 /var/lib/docker/500000.500000디렉토리가 생성 되었는지 확인 합니다.

    이제 컨테이너 내부에는 rootuser1, 호스트에 ns1-rootns1-user1, 일치하는 ID가 있습니다.

    업데이트 : 루트가 아닌 사용자가 컨테이너 (예 : user1 1000 : 1000)에 고정 ID를 갖도록 보장하려면 이미지 빌드 중에 명시 적으로 생성합니다.

테스트 드라이브:

  1. 볼륨 디렉터리 준비

    mkdir /vol1
    chown ns1-root:ns1-root /vol1
    
  2. 컨테이너에서 시도

    docker run --rm -ti -v /vol1:/vol1 busybox sh
    echo "Hello from container" > /vol1/file
    exit
    
  3. 호스트에서 시도

    passwd ns1-root
    login ns1-root
    cat /vol1/file
    echo "can write" >> /vol1/file
    

휴대용이 아니며 해킹처럼 보이지만 작동합니다.


docker cp명령 을 사용하여 권한 문제를 방지 할 수 있습니다 .

소유권은 대상의 사용자 및 기본 그룹으로 설정됩니다. 예를 들어 컨테이너에 복사 된 파일 UID:GID은 루트 사용자 로 만들어집니다 . 로컬 시스템에 복사 된 파일 UID:GIDdocker 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

참고URL : https://stackoverflow.com/questions/35291520/docker-and-userns-remap-how-to-manage-volume-permissions-to-share-data-betwee

반응형