Docker에서 컨테이너를 지정하고 실행 가능한 사용자로 시작

7257 단어 Docker

배경.


도커 컨테이너 안에서 일을 좀 하다가 이런 문제에 부딪혔다.
$ docker run --rm -it -v ${PWD}/work:/work ubuntu:14.04 

< ちょっとした作業 >

root@02fcfbf664e1:/# mkdir /work/hoge
# コンテナ内で、マウントしたディレクトリ内にファイル作成
root@02fcfbf664e1:/# vi /work/hoge/container_de_sakusei

< 作業終了 >
root@02fcfbf664e1:/# exit
exit

# ホストで、さっき作成したファイルを(ディレクトリごと)削除
$ rm -rf ./work/hoge
rm: cannot remove ‘./work/hoge/container_de_sakusei’: Permission denied

파일을 삭제할 수 없습니다.
이유는 간단하다. 용기 안에서 루트 사용자로 파일을 만들었기 때문에 ona는 루트가 되었다.
$ ls -l ./work/hoge/
total 4
-rw-r--r-- 1 root root 10 Aug 18 02:02 container_de_sakusei
그렇다면 -u 옵션을 설치하여 실행 사용자를 바꾸면 좋겠다고 생각했는데 또 다른 문제가 생겼습니다.
$ docker run --rm -it -v ${PWD}/work:/work -u $(id -u):$(id -g)  ubuntu:14.04 
groups: cannot find name for group ID 1002
I have no name!@ef625fbaf1c8:/$ 
I have no name!@ef625fbaf1c8:/$ sudo ls
sudo: unknown uid 1001: who are you?

sudo를 사용할 수 없습니다.스케줄러:뭐,당연하죠.
컨테이너 안에 사용자/그룹이 없기 때문에 groups: cannot find name for group ID 나오거나 I have no name!라고 말하는 것도 어쩔 수 없지만 사용할 수 없음sudo은 고통스럽다.

하고 싶은 일

  • uid/gid를 지정하여 시작하려고 합니다
  • sudo
  • 를 사용하고 싶습니다.
    한 마디로 하면 앱으로 추가 포장을 하거나 용기 <-> 호스트 간에 권한에 얽매이지 않고 파일을 공유하고 싶다는 것이다.

    어떻게 실현합니까


    언어로 설명하는 것보다 Docker file과 entrypoint의 스크립트를 보는 것이 더 빠를 것 같습니다.
    Dockerfile
    FROM ubuntu:14.04
    
    # 一般ユーザ名を設定
    ENV USER_NAME=developer
    
    # sudoを使用できるようにする
    RUN echo "${USER_NAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/${USER_NAME}
    
    # 一般ユーザがユーザ/グループを追加できるようにする
    # entrypoint.sh内でパーミッションを元に戻す
    RUN chmod u+s /usr/sbin/useradd \
        && chmod u+s /usr/sbin/groupadd
    
    COPY entrypoint.sh /entrypoint.sh
    ENTRYPOINT ["/entrypoint.sh"]
    CMD ["bash"]
    
    entrypoint.sh
    #!/bin/bash -e
    
    USER_ID=$(id -u)
    GROUP_ID=$(id -g)
    
    # グループを作成する
    if [ x"$GROUP_ID" != x"0" ]; then
        groupadd -g $GROUP_ID $USER_NAME
    fi
    
    # ユーザを作成する
    if [ x"$USER_ID" != x"0" ]; then
        useradd -d /home/$USER_NAME -m -s /bin/bash -u $USER_ID -g $GROUP_ID $USER_NAME
    fi
    
    # パーミッションを元に戻す
    sudo chmod u-s /usr/sbin/useradd
    sudo chmod u-s /usr/sbin/groupadd
    
    exec $@
    
    하는 일은 아래와 같다.
    1. "developer"사용자가 암호 없이 sudo를 실행할 수 있도록 sudoers를 설정합니다
    2. 일반 사용자가 useraddgroupadd 명령을 수행할 수 있도록 SUID 부여
    3. -u 옵션이 지정한 uid/gid를 가진'developer'사용자 만들기
    4. 두 명령의 권한을 취소(SUID 획득)하여 일반 사용자가 명령useradd과 명령groupadd을 실행할 수 없도록 한다.
    1.Docker file에서 사전docker build 진행, 3.그리고entrypoint의 케이스 스크립트에서 용기를 시작할 때 docker run 진행됩니다.
    위의 예에서 ubuntu:14.04의 이미지를 사용했지만 ubuntu:16.04와centos 등의 인상도 마찬가지일 것이다.
    SUID(Set User ID)에 익숙하지 않은 사람이 있을 수 있지만 이것은 특별한 접근권이다.passwd 명령 실행 파일이 부여됩니다.
    실행 파일을 실행할 때는 일반적으로 해당 파일을 실행하는 사용자의 권한으로 실행되지만 SUID가 설정된 실행 파일인 경우 실행 파일 소유자의 권한에 따라 실행됩니다.
    예를 들어 passwd 명령은 자신의 암호 설정을 위해 일반 사용자라도 실행할 수 있지만, 이 때 암호화된 암호를 루트에서read/write의/etc/shadow에만 쓸 수 있어야 합니다.일반 사용자가 실행하더라도 passwd 명령 실행 파일의 소유자 루트가 실행된 것이다.
    이번의 경우 useradd 명령과 groupadd 명령에 SUID를 설정하여 일반 사용자처럼 사용자/그룹을 추가할 수 있습니다.

    사용법


    Docker 이미지 만들기


    위의 Docker file 및 entrypoint.쉬docker build만 만들면 된다.
    # Dockerfileを作成
    $ vi Dockerfile
    
    # entrypointとなるシェルスクリプトを作成
    $ vi entrypoint.sh
    
    # 実行権限を付与
    $ chmod a+x entrypoint.sh
    
    # Docker imageをビルド
    $ docker build -t ubuntu_sudo:14.04 .
    

    Docker 컨테이너 시작


    필요에 따라 옵션을 수정하십시오.
    $ docker run \
        --rm -it \
        -u $(id -u):$(id -g) \
        -v ${PWD}/work:/work \
        ubuntu_sudo:14.04 
    
    developer@08f6830cc60a:/$ id
    uid=1001(developer) gid=1002(developer) groups=1002(developer)
    
    developer@08f6830cc60a:/$ sudo ls 
    bin  boot  dev  entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  work
    

    추가:기타 방법


    하고 싶은 일을 이루는 방법은 아직 많다.

    고유 Docker 이미지 만들기


    이것은 사용자와 sudo 설정을 추가해서 자신만의 Docker 이미지를 준비하는 방법입니다.
    이것은 다른 사람이 한 예 중 가장 많은 방법이다.
    Dockerfile
    FROM ubuntu:14.04
    
    ENV USER_ID=1000 \
        GROUP_ID=1000 \
        USER_NAME=developer
    
    RUN groupadd -g $GROUP_ID $USER_NAME \
        useradd -d /home/$USER_NAME -m -s /bin/bash -u $USER_ID -g $GROUP_ID \
        echo "${USER_NAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/${USER_NAME}
    
    이 방법이 취할 수 없는 점은 사용자 간에 이미지를 반복해서 사용할 수 없다는 것이다.
    예를 들어 Rubby와 Python 등 개발 환경을 Docker 이미지로 준비하면 그 외에 모든 사람이 자신이 설정한 uid/guid 이미지를 관리해야 한다.
    또한 여러 대의 기계를 뛰어넘을 때 호스트 간 사용자의 id/gid가 다르면 이미지를 다시 만들어야 한다.

    호스트 인증 정보 공유


    호스트가 가지고 있는 인증 정보를 용기에 직접 불러오는 방법입니다.
    $ docker run \
        --rm -it \
        -u $(id -u):$(id -g) \
        -v /etc/group:/etc/group:ro \
        -v /etc/passwd:/etc/passwd:ro \
        -v /etc/shadow:/etc/shadow:ro \
        -v /etc/sudoers.d:/etc/sudoers.d:ro \
        ubuntu:14.04
    
    이 방법의 이유는 용기 시작 (docker run) 의 명령 옵션이 길기 때문입니다.(나만 그렇게 생각할지도 몰라.)
    검증되지 않았습니다. :ro (read only) 용기에서 사용자 추가/삭제 등을 잊어버리면 호스트에 영향을 줄 수 있습니다.
    또한 용기 안에 있는 기존 시스템 사용자/그룹과 호스트의 시스템 사용자/그룹의 id에 편차가 있으면 고장이 발생할 수 있습니다.
    또한 호스트의 sudoers 정보를 계승해야 하기 때문에 호스트가 sudo를 사용할 수 없으면 용기 내에서도 사용할 수 없다.이것은 아마도 가장 치명적일 것이다.
    하지만 기존의 기본적인 인상을 그대로 사용하는 것이 인기라고 생각합니다.

    응용 프로그램


    이번 내용을 바탕으로 데스크톱 환경을 만들었다.다음 기사를 참조하십시오.
    Docker에서 sudo와 함께 사용할 데스크톱 환경 만들기(XRDP 편)

    좋은 웹페이지 즐겨찾기