permission denied가 발생하는 문제
Linux상에서 Docker 컨테이너 내에 있는 volume을 mount했을 때, 호스트에서 액세스할 경우 권한 문제가 발생하는 경우가 있다. 이는 호스트 OS에서 사용하고 있는 유저와 컨테이너 내에서 사용하고 있는 유저의 UID와 GID가 불일치하는 경우가 원인인듯하다. 따라서 Docker for Mac/Windows에서는 이러한 문제는 거의 발생하지 않는다. UID와 GID과 불일치하는 경우는 다음과 같은 경우를 일컫는다.
호스트 OS에서 터미널을 연 뒤에 id 커맨드를 입력하면 다음과 같은 결과가 출력되는데 반해,
$ id
uid=1000(test) gid=1000(test) groups=0(test)
컨테이너 내에 들어가서 id 커맨드 결과를 보면 아래와 같이 호스트상의 UID와 GID가 동일하지 않는 것이다.
# (컨테이너 내부)
$ id
uid=0(root) gid=0(root) groups=0(root)
해결방법
해결 방법 1 : mount한 volume 유저의 권한을 직접 바꿔준다.
permission denied가 발생하고 있는 디렉토리, 파일의 권한을 직접 커맨드로 변경하는 것으로 해결할 수 있다. chmod같은 커맨드를 이용하는 방법으로 말이다. chmod에 대한 설명은 다른 포스팅에서 상세하게 설명하고 있으니 이 포스팅을 참고해주길 바란다.
$ chmod 777 /var/project
해결 방법 2 : 유저 정보가 적혀 있는 파일을 읽기 전용으로 mount한다.
컨테이너 내의 UID와 GID 호스트 OS와 동일하게 되도록 컨테이너를 실행할 때에 UID와 GID를 지정한다.
혹은 /etc/passwd와의 불일치가 발생하지 않도록 호스트 OS의 /etc/passwd를 마운트해줄 필요가 있다.
마지막으로, 컨테이너 쪽에서 /etc/passwd의 마음대로 변경하지 않도록 하기 위해 읽기 전용 read only(:ro) 를 지정해서 마운트한다.
$docker run \
-u "$(id -u $USER):$(id -g $USER)" \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group:ro \
-it ubuntu
위에서 봤던 id 커맨드로 호스트쪽과 컨테이너 내의 UID와 GID를 확인하면 일치되도록 변경됐음을 알 수 있다.
$ id
uid=1000(test) gid=1000(test) groups=1000(test)
# (컨테이너안)
test@hogehoge:~$ id
uid=1000(test) gid=1000(test) groups=1000(test)
다만, 이 방법의 단점은 다른 플랫폼간에서는 Docker 파일등을 공유하는 것이 불가능해지게 된다.
해결법 3 : 컨테이너 생성시에 유저와 그룹을 추가한다.
호스트 OS의 유저(UID)와 그룹(GID)를 환경변수로써 전달하고, 컨테이너 내에서 유저와 그룹을 추가하는 방법이다. 먼저 Docker file을 다음과 같이 컨테이가 종료하지 않고 /bin/bash형으로 대화 모드로 움직이도록 한다.
# Dockerfile
FROM ubuntu:latest
RUN apt update \
&& apt -yq dist-upgrade \
&& apt install -yq --no-install-recommends \
sudo
COPY entrypoint.sh /var/tmp
CMD bash -E /var/tmp/entrypoint.sh && /bin/bash
그리고 dockr-compose.yml 파일에는 다음과 같이 환경변수로, 유저(UID), 그룹(GID)를 전달하도록 설정한다.
# docker-compose.yml
version: "3"
services:
override:
image: example/override-ids
build: .
container_name: override
environment:
- USER_NAME
- USER_ID
- GROUP_NAME
- GROUP_ID
volumes:
- ./:/mnt/working
tty: true
그리고 쉘 스크립트도 하나 작성한다. user, groupadd로 유저와 그룹을 추가. usermode로 유저와 그룹을 설정한다.
# entrypoint.sh
useradd -s /bin/bash -m ${USER_NAME}
export HOME=/home/${USER_NAME}
usermod -u ${USER_ID} ${USER_NAME}
groupadd -g ${GROUP_ID} ${GROUP_NAME}
usermod -g ${GROUP_NAME} ${USER_NAME}
$ docker-compose build
$ USER_NAME=$(id -un) \ USER_ID=$(id -u) \
GROUP_NAME=$(id -gn) \ GROUP_ID=$(id -g) \
sudo -E docker-compose up -d
docker 컨테이너를 빌드한 후 id 커맨드로 확인하면 일치된 상태로 출력됨을 알 수 있다.
참고자료
'IT > 기초 지식' 카테고리의 다른 글
[UML] 클래스 다이어그램 (0) | 2022.03.30 |
---|---|
[Docker] NVIDIA Container Toolkit(NVIDIA Docker)의 동작원리 (0) | 2022.02.18 |
[AWS] 기존의 EC2 인스턴스에 새로운 EBS 연결(mount)하기 (2) | 2022.02.09 |
[Docker/Linux] Linux환경에서 GPU가 적용된 Docker 컨테이너 만들기 (0) | 2022.02.09 |
[AWS/Linux] AWS EC2 인스턴스에 Ubuntu 데스크톱 환경 만들기 (0) | 2022.02.07 |