잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).

여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.

감사합니다. -현록

후원해주실 분은 여기로→

현록의 기록저장소

컨테이너에서 로그나 파일을 생성할 수 없는 문제 본문

Study/Docker

컨테이너에서 로그나 파일을 생성할 수 없는 문제

현록 2023. 11. 11. 22:53

[개요]

[volume mount의 문제]

[volume mount의 문제 해결]

[실행과 상대 경로의 문제]

[실행과 상대 경로의 문제 해결]

 

 

Docker container cannot make log file

 

 


[개요]

 

호스트에서 실행할 때는 로그를 잘만 생성하는데,

이걸 컨테이너에서 실행하면 로그를 생성하지 못하는 경우가 있다.

특히 Dockerfile에서 USER ~로 유저를 전환해서 실행할 때 이런 문제에 직면하는 경우가 있다.

 

 


[volume mount의 문제]

 

먼저 컨테이너 실행 예시를 위해 Dockerfiledocker-compose.yml을 가져왔다.

정말 별거 없는 심플한 상황을 만들었다.

 

 

Dockerfile

FROM ubuntu

RUN mkdir /mybind

RUN adduser user001

RUN chown -R user001:user001 /mybind

USER user001

RUN touch /mybind/a

RUN touch /mybind/b

RUN touch /mybind/c

ENTRYPOINT [ "bin/bash", "-c", "while true; do touch /mybind/d; touch /mybind/e; touch /mybind/f; sleep 1; done;" ]

맨 처음 root가 /mybind 디렉터리를 만들어주고,

user001이라는 유저를 생성해준 후,

/mybind 디렉터리의 소유권을 user001이 가지도록 해주고

user001로 유저 전환을 한다.

그리고 /mybind에 a,b,c 파일을 생성한 후,

이제는 d,e,f 파일을 1초마다 생성하는 반복 스크립트를 무한히 동작하게 된다.

 

 

docker-compose.yml

services:

  bind-test:

    build:

      context: .

      dockerfile: ./Dockerfile

      no_cache: true

    image: image-bind-test

    container_name: cont-bind-test

    volumes:

      - ./bind-with-container:/mybind

    stdin_open: true

    tty: true

    hostname: bind-test

호스트의 ./bind-with-container 디렉터리를 컨테이너의 /mybind 디렉터리와 연결하는 것 외에

특별한 것은 없다.

(여기선 docker compose로 실행하지만,

docker run ~ -v ./bind-with-container:/mybind ~ 로 컨테이너를 만들어 실행해도 상관없이 같은 상황이 된다.)

 

 

desktop@vm:~/Docker/bind-test$ ls -alR

.:

total 16

drwxrwxr-x 2 desktop desktop 4096 11월 11 21:38 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 20:39 ..

-rw-rw-r-- 1 desktop desktop  270 11월 11 21:15 docker-compose.yml

-rw-rw-r-- 1 desktop desktop  280 11월 11 21:34 Dockerfile

호스트의 유저는 desktop이라는 이름이고, 본 디렉터리에는 위 예시 파일만 있을 뿐이다.

이제 컨테이너를 만들어보자.

 

 

desktop@vm:~/Docker/bind-test$ docker compose up -d

[+] Running 1/1

 ✔ Container cont-bind-test  Started                                                                     0.0s 

desktop@vm:~/Docker/bind-test$ ls -alR

.:

total 20

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 20:39 ..

drwxr-xr-x 2 root    root    4096 11월 11 21:39 bind-with-container

-rw-rw-r-- 1 desktop desktop  270 11월 11 21:15 docker-compose.yml

-rw-rw-r-- 1 desktop desktop  280 11월 11 21:34 Dockerfile

./bind-with-container:

total 8

drwxr-xr-x 2 root    root    4096 11월 11 21:39 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 ..

volume mount 설정대로

./bind-with-container가 만들어졌는데,

기대와 달리 안에는 어떤 파일도 없다.

 


더보기

먼저 volume bind mount는

host -> container의 방향으로만 진행하기 때문에,

Dockerfile에서 명시한 RUN touch /mybind/a 들은 실제론 실행되어서 만들어졌으나

volume bind 과정에서 host의 디렉터리가 덮어쓰면서 사라진 것이다.

아쉽게도 반대 방향의 복사를 시작시 자동으로 해올 순 없다.

bind 시점이 Dockerfile의 마지막 줄 이후의 시점이기 때문.

 

컨테이너의 파일을 가져오고 싶다면,

덮어씌워지지 않게 다른 곳을 bind해서

내부로 들어가 원하는 파일들을 bind된 곳으로 이동시킨 후,

host에서 파일을 가진 채 해당 파일들을 덮어쓸 수 있도록 bind를 설정하는 것 밖에는...


 

 

그럼 d,e,f는 왜 없을까??

desktop@vm:~/Docker/bind-test$ docker logs cont-bind-test

touch: cannot touch '/mybind/d': Permission denied

touch: cannot touch '/mybind/e': Permission denied

touch: cannot touch '/mybind/f': Permission denied

touch: cannot touch '/mybind/d': Permission denied

touch: cannot touch '/mybind/e': Permission denied

touch: cannot touch '/mybind/f': Permission denied

음... 무한히 1초마다 파일 생성은 시도하는데, 권한 문제가 발생한다.

내부로 들어가서 보자.

 

desktop@vm:~/Docker/bind-test$ docker exec -it cont-bind-test /bin/bash

user001@bind-test:/$ ls -al

total 64

drwxr-xr-x   1 root root 4096 Nov 11 12:35 .

drwxr-xr-x   1 root root 4096 Nov 11 12:35 ..

-rwxr-xr-x   1 root root    0 Nov 11 12:35 .dockerenv

lrwxrwxrwx   1 root root    7 Oct  4 02:08 bin -> usr/bin

drwxr-xr-x   2 root root 4096 Apr 18  2022 boot

drwxr-xr-x   5 root root  360 Nov 11 12:39 dev

drwxr-xr-x   1 root root 4096 Nov 11 12:35 etc

drwxr-xr-x   2 root root 4096 Apr 18  2022 home

lrwxrwxrwx   1 root root    7 Oct  4 02:08 lib -> usr/lib

lrwxrwxrwx   1 root root    9 Oct  4 02:08 lib32 -> usr/lib32

lrwxrwxrwx   1 root root    9 Oct  4 02:08 lib64 -> usr/lib64

lrwxrwxrwx   1 root root   10 Oct  4 02:08 libx32 -> usr/libx32

drwxr-xr-x   2 root root 4096 Oct  4 02:08 media

drwxr-xr-x   2 root root 4096 Oct  4 02:08 mnt

drwxr-xr-x   2 root root 4096 Nov 11 12:39 mybind

drwxr-xr-x   2 root root 4096 Oct  4 02:08 opt

dr-xr-xr-x 368 root root    0 Nov 11 12:39 proc

drwx------   2 root root 4096 Oct  4 02:12 root

drwxr-xr-x   5 root root 4096 Oct  4 02:12 run

lrwxrwxrwx   1 root root    8 Oct  4 02:08 sbin -> usr/sbin

drwxr-xr-x   2 root root 4096 Oct  4 02:08 srv

dr-xr-xr-x  13 root root    0 Nov 11 12:39 sys

drwxrwxrwt   2 root root 4096 Oct  4 02:12 tmp

drwxr-xr-x  14 root root 4096 Oct  4 02:08 usr

drwxr-xr-x   1 root root 4096 Oct  4 02:12 var

user001@bind-test:/$ exit

exit

/mybind 디렉터리의 소유자가 root:root인 것을 볼 수 있다.

그래서 해당 디렉터리 내부에 파일을 생성할 수 없는 것.

 

그런데, Dockerfile에서 분명 RUN chown -R user001:user001 /mybind를 해줬는데, 왜 소유권이 안 바뀌어있을까?

이게 이번 케이스의 핵심이다.

 

 

컨테이너를 돌렸을 때, 자동으로 ./bind-with-container 디렉터리를 만들어주던 것을 위에서 봤었다.

desktop@vm:~/Docker/bind-test$ ls -alR

.:

total 20

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 20:39 ..

drwxr-xr-x 2 root    root    4096 11월 11 21:39 bind-with-container

-rw-rw-r-- 1 desktop desktop  270 11월 11 21:15 docker-compose.yml

-rw-rw-r-- 1 desktop desktop  280 11월 11 21:34 Dockerfile

./bind-with-container:

total 8

drwxr-xr-x 2 root    root    4096 11월 11 21:39 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 ..

나는 desktop 계정으로 docker 명령어를 실행했지만,

디렉터리를 자동으로 만들 때 root가 만든 것이다.

 

desktop@vm:~/Docker/bind-test$ id

uid=1000(desktop) gid=1000(desktop) groups=1000(desktop),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),

122(lpadmin),135(lxd),136(sambashare),999(docker)

desktop에 docker(999) 그룹을 추가해줬어서

딱히 sudo docker ~ 한 것이 아닌데도.

어쨌든 docker가 자동으로 만들 때 root가 디렉터리를 만들게 된다.

 

 

사실 volume mount를 할 때,

host의 디렉터리 소유권 (uid, gid)가 그대로 컨테이너에 전파된다.

desktop@vm:~/Docker/bind-test$ sudo su

root@vm:/home/desktop/Docker/bind-test# id

uid=0(root) gid=0(root) groups=0(root)

 

root의 uid, gid가 각각 0이라,

컨테이너에도 0:0으로 소유권을 덮어버리는데,

컨테이너에도 0은 root이기 때문에,

/mybind의 소유권이 0:0인 root:root로 덮어써진 것.

실제로 volume 마운트를 하지 않고 컨테이너를 만들면

DockerfileRUN chown -R user001:user001 /mybind 한 대로 user001 소유의 디렉터리로 나온다.

이게 다 마운트시 소유권을 덮어써버려서 그렇다.

 

 

해결책은 간단하다.

host의 원본 디렉터리 소유 유저의 uid가 컨테이너 유저의 uid와 같으면 된다.

uid를 맞출 수 없는 상황도 있다. 그럼 gid를 맞추면 된다.

 

 


[volume mount의 문제 해결]

 

컨테이너에서 처음으로 adduser를 별다른 옵션없이 수행했으므로,

user001의 uid는 1000일 것이다.

desktop@vm:~/Docker/bind-test$ docker exec -it cont-bind-test /bin/bash

user001@bind-test:/$ id

uid=1000(user001) gid=1000(user001) groups=1000(user001)

 

 

host의 uid도 좋게도 1000으로 일치하는 상황이다.

desktop@vm:~/Docker/bind-test$ id

uid=1000(desktop) gid=1000(desktop) groups=1000(desktop),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),

122(lpadmin),135(lxd),136(sambashare),999(docker)

 

 

이러면 아주 간단한 상황이다.

 

하지만 host의 uid가 2003 같은 상황이라면??

Dockerfile에서 유저생성시 RUN adduser -u 2003 user001 처럼 uid를 지정해서 생성해준다.

 

뭐 어떻게 해도 uid를 맞추기는 힘든 상황이다?? (혹은 여러 소유권이 다른 여러 디렉터리를 마운트해야한다거나)

만약 host의 원본 디렉터리의 그룹소유권을 통일 시켜주고 해당 gid로 그룹을 맞춰주자.

gid가 4002라고 하면,

Dockerfile에서 먼저 RUN addgroup -g 4002 group001로 gid가 같은 그룹을 생성.

이후 RUN adduser -G 4002 user001 (g는 기본그룹을 수정하지만, G는 기본그룹에 추가되도록)로 추가 그룹을 설정해준다.

유저 생성 후에 RUN addgroup -g 4002 user001로 추가 그룹을 줘도 된다.

 

 

위의 경우들이라면 Dockerfile을 수정하고 다시 컨테이너를 만들어야한다.

desktop@vm:~/Docker/bind-test$ docker stop cont-bind-test

cont-bind-test

desktop@vm:~/Docker/bind-test$ docker rm cont-bind-test

cont-bind-test

desktop@vm:~/Docker/bind-test$ docker rmi image-bind-test

Untagged: image-bind-test:latest

Deleted: sha256:61f81705fd4fe64c647d9160517983facd615d231aec3b267a3e3464c3ee8738

(기존 컨테이너 중지, 삭제, 빌드된 이미지 삭제)

 

이미 uid나 gid가 같다면 그냥 정지만 해두고 해결 후 재실행하자.

desktop@vm:~/Docker/bind-test$ docker stop cont-bind-test

cont-bind-test

 

 

 

desktop@vm:~/Docker/bind-test$ sudo chown -R desktop:desktop ./bind-with-container

desktop@vm:~/Docker/bind-test$ ls -alR

.:

total 20

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 20:39 ..

drwxr-xr-x 2 desktop desktop 4096 11월 11 21:39 bind-with-container

-rw-rw-r-- 1 desktop desktop  270 11월 11 21:15 docker-compose.yml

-rw-rw-r-- 1 desktop desktop  280 11월 11 21:34 Dockerfile

./bind-with-container:

total 8

drwxr-xr-x 2 desktop desktop 4096 11월 11 21:39 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 ..

host의 컨테이너 소유권을 수정해주고, 다시 컨테이너를 실행하자.

desktop@vm:~/Docker/bind-test$ docker compose up -d

[+] Running 1/1

 ✔ Container cont-bind-test  Started                                                                     0.0s 

desktop@vm:~/Docker/bind-test$ ls -alR

.:

total 20

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 20:39 ..

drwxr-xr-x 2 desktop desktop 4096 11월 11 21:41 bind-with-container

-rw-rw-r-- 1 desktop desktop  270 11월 11 21:15 docker-compose.yml

-rw-rw-r-- 1 desktop desktop  280 11월 11 21:34 Dockerfile

./bind-with-container:

total 8

drwxr-xr-x 2 desktop desktop 4096 11월 11 21:41 .

drwxrwxr-x 3 desktop desktop 4096 11월 11 21:39 ..

-rw-r--r-- 1 desktop desktop    0 11월 11 21:41 d

-rw-r--r-- 1 desktop desktop    0 11월 11 21:41 e

-rw-r--r-- 1 desktop desktop    0 11월 11 21:41 f

d,e,f 파일이 잘 생성되었다.

 

 

desktop@vm:~/Docker/bind-test$ docker exec -it cont-bind-test /bin/bash

user001@bind-test:/$ ls -al

total 64

drwxr-xr-x   1 root    root    4096 Nov 11 12:35 .

drwxr-xr-x   1 root    root    4096 Nov 11 12:35 ..

-rwxr-xr-x   1 root    root       0 Nov 11 12:35 .dockerenv

lrwxrwxrwx   1 root    root       7 Oct  4 02:08 bin -> usr/bin

drwxr-xr-x   2 root    root    4096 Apr 18  2022 boot

drwxr-xr-x   5 root    root     360 Nov 11 12:41 dev

drwxr-xr-x   1 root    root    4096 Nov 11 12:35 etc

drwxr-xr-x   2 root    root    4096 Apr 18  2022 home

lrwxrwxrwx   1 root    root       7 Oct  4 02:08 lib -> usr/lib

lrwxrwxrwx   1 root    root       9 Oct  4 02:08 lib32 -> usr/lib32

lrwxrwxrwx   1 root    root       9 Oct  4 02:08 lib64 -> usr/lib64

lrwxrwxrwx   1 root    root      10 Oct  4 02:08 libx32 -> usr/libx32

drwxr-xr-x   2 root    root    4096 Oct  4 02:08 media

drwxr-xr-x   2 root    root    4096 Oct  4 02:08 mnt

drwxr-xr-x   2 user001 user001 4096 Nov 11 12:41 mybind

drwxr-xr-x   2 root    root    4096 Oct  4 02:08 opt

dr-xr-xr-x 366 root    root       0 Nov 11 12:41 proc

drwx------   2 root    root    4096 Oct  4 02:12 root

drwxr-xr-x   5 root    root    4096 Oct  4 02:12 run

lrwxrwxrwx   1 root    root       8 Oct  4 02:08 sbin -> usr/sbin

drwxr-xr-x   2 root    root    4096 Oct  4 02:08 srv

dr-xr-xr-x  13 root    root       0 Nov 11 12:41 sys

drwxrwxrwt   2 root    root    4096 Oct  4 02:12 tmp

drwxr-xr-x  14 root    root    4096 Oct  4 02:08 usr

drwxr-xr-x   1 root    root    4096 Oct  4 02:12 var

컨테이너의 /mybind 디렉터리의 소유권을 보면 원하는 대로 유지되어있다.

(사실은 원하는 목표의 uid:gid로 덮어쓴거지만)

 

 


[실행과 상대 경로의 문제]

 

어.. 그런데 딱히 위의 문제가 아닌데도 로그 파일들을 생성할 수 없다면..??

특히 로그 파일 생성 위치가 절대 경로가 아니라 상대 경로인 경우일겁니다.

 

로컬 빌드된 파일을 생성해봅시다.

여기선 java의 .jar 파일로 예시를 들겠습니다.(뭐 go lang이든 python이든...)

 

.jar 파일을 생성해주세요.

 

그리고 터미널의 위치를 변경하여 그곳에서 .jar파일을 실행해줍니다.(java -jar ~.jar ~)

그러면 해당 위치를 기준으로 로그 디렉터리를 생성할겁니다.

 

일부러 위치를 변경하여 그곳에서 다시 .jar파일을 실행해보세요.

또 그 곳 기준으로 로그 디렉터리를 생성할겁니다.

 

혹시 Dockerfile에서 USER ubuntu001 이후,

WORKDIR ~ 를 빼먹진 않으셨나요?

위의 케이스와 겹치는 문제가 어느 정도 있는데,

user001의 권한을 갖는 /mybind로 이동해서 컨테이너가 빌드 파일을 실행한다면 하위 디렉터리도 만들고 파일도 제대로 생성하지만,

WORKDIR /mybind가 없다면

root:root권한인 /에서 하위 디렉터리나 파일을 생성할 수 없어서 로그 파일을 남기지 못하는 상황입니다.

 

 


[실행과 상대 경로의 문제 해결]

 

[volume mount의 문제 해결]이 된 상태라면 이번 문제는 딱히 어렵지 않습니다.

CMD/ENTRYPOINT [ ~ ] 이전에 user001이 권한을 가진 곳으로 WORKDIR ~를 해주세요.

 

 

'Study > Docker' 카테고리의 다른 글

Docker Compose 사용 (docker-compose.yml)  (0) 2023.01.04
Dockerfile 작성 (Dockerfile로 배포)  (0) 2023.01.03
Docker 마운팅  (0) 2021.04.02
Docker 실행  (0) 2021.04.01
Docker 이미지들 (Docker Hub)  (0) 2021.03.31
Comments

잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).

여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.

감사합니다. -현록

후원해주실 분은 여기로→