본문 바로가기

직접 만든 소프트웨어, 두 가지 개발 기록

구현 구조와 적용 범위, 확인한 기능과 남은 한계를 함께 기록합니다.

소프트웨어개발

Docker bind mount permission denied 해결: 경로·UID·GID·SELinux 점검

by 아빠띠띠뽀 2026. 10. 4.

Docker 컨테이너에서 /app/data에 파일을 저장할 때 permission denied가 발생한다면 Docker 소켓 권한과 파일 마운트 권한을 먼저 구분하세요. 컨테이너가 이미 실행되고 앱의 파일 쓰기만 실패한다면 연결한 호스트 경로, 실제 프로세스의 사용자 ID, 읽기 전용 설정과 SELinux 정책을 차례로 확인하는 편이 좋습니다. 디렉터리 전체에 chmod 777을 적용하면 증거와 접근 범위를 함께 잃을 수 있습니다.

호스트 폴더와 컨테이너를 연결한 파일 경로에서 사용자 ID와 권한을 확인하는 개념 이미지
직접 생성한 개념 이미지. 호스트 파일 경로·컨테이너 프로세스·접근 권한의 관계를 표현했습니다.

1. 오류가 난 경로와 시점을 먼저 나누세요

발생 상황 확인할 대상
docker.sock 접근에서 거부 Docker 데몬 연결 권한·context
컨테이너 생성 중 소스 경로 오류 데몬 호스트의 실제 경로·경로 생성 권한
앱이 마운트 파일을 열 때 거부 프로세스 ID·파일 소유자·상위 경로·정책
Read-only file system 오류 읽기 전용 마운트와 앱의 쓰기 요구

첫 번째 상황은 Docker daemon socket permission denied 점검과 연결됩니다. 이 글은 두 번째부터 네 번째 상황을 다룹니다. Docker bind mount 문서처럼 bind mount의 소스는 CLI를 실행한 컴퓨터가 아니라 Docker 데몬 호스트를 기준으로 합니다. 원격 context를 사용하면서 노트북의 폴더 권한만 바꾸면 문제가 해결되지 않을 수 있습니다.

2. Source·Destination·RW를 실제 컨테이너에서 확인하세요

다음은 app이라는 컨테이너와 /srv/myapp/data라는 경로를 가정한 읽기 전용 확인 명령입니다. 실제 이름과 경로로 바꾸세요. stat -c와 namei는 GNU/Linux 환경 기준이며 macOS 기본 도구의 옵션과 다를 수 있습니다. 출력에 민감한 경로가 포함되면 외부에 공유하기 전에 제거합니다.

docker context show
docker inspect app --format '{{json .Mounts}}'
docker inspect app --format '{{.Config.User}}'
stat -c '%u:%g %a %n' /srv/myapp/data
namei -l /srv/myapp/data

Mounts에서 Type이 bind인지, Source와 Destination이 의도한 경로인지, RW가 true인지 확인하세요. RW=true는 마운트가 쓰기를 허용한다는 뜻이고 현재 앱 사용자에게 파일 쓰기 권한이 있다는 증거는 아닙니다. 상위 디렉터리마다 경로를 통과할 권한도 필요합니다. namei가 설치되어 있지 않으면 각 상위 경로의 소유자와 권한을 따로 확인하세요.

이미지의 설정된 사용자와 실행 중인 앱의 유효 사용자도 구별합니다. 셸이 포함된 이미지에서는 docker exec app id로 새로 실행한 명령의 ID를 볼 수 있지만, 앱이 시작 후 권한을 낮추었다면 그 결과가 앱의 유효 ID와 같다고 단정할 수 없습니다. 앱 프로세스 정보를 함께 확인하고, 셸·id가 없는 최소 이미지에는 억지로 도구를 설치하는 대신 배포 설정과 제공된 진단 방법을 사용하세요.

3. UID·GID 불일치는 전용 데이터 경로에서 해결하세요

일반적인 Linux Docker에서 사용자 네임스페이스 매핑을 사용하지 않는 경우를 가정해 보겠습니다. 앱이 UID 10001·GID 10001로 실행되는데 호스트 데이터 폴더가 root:root·0755라면, 해당 앱 사용자는 폴더를 볼 수 있어도 새 파일을 만들지 못할 수 있습니다. 파일 시스템의 접근 판단에는 이름보다 숫자 ID가 중요합니다.

이때 앱 전용 폴더의 소유자를 맞추거나 승인된 공유 그룹에 필요한 쓰기 권한을 주는 방법을 검토합니다. 아래는 매핑을 사용하지 않는 환경에서 소유권 변경이 승인된 전용 데이터 폴더에만 적용하는 예시입니다. 실제 ID와 기존 소유권을 먼저 기록하고 백업하세요. 상위 디렉터리나 기존 모든 파일까지 자동으로 바뀌지는 않습니다.

sudo chown 10001:10001 /srv/myapp/data
sudo chmod 0750 /srv/myapp/data

시스템 경로 전체에 재귀 chown을 실행하거나 모든 사용자에게 쓰기를 허용하지 않습니다. 기존 파일은 별도로 필요한 범위를 확인하세요. Compose user 설정도 이미지의 실행 요구를 따릅니다. 숫자만 바꿔 실행하면 시작 시 필요한 작업이나 다른 경로 접근이 실패할 수 있습니다.

4. rootless·사용자 네임스페이스·SELinux는 별도로 점검하세요

rootless UID/GID 매핑과 userns-remap 문서에서 호스트와 컨테이너 ID의 대응이 다를 수 있음을 확인할 수 있습니다. 이 환경에서는 컨테이너의 UID 10001을 호스트의 UID 10001과 곧바로 같다고 취급하면 안 됩니다. 매핑 설정과 호스트의 실제 소유자를 확인한 뒤 해당 운영 방식에 맞는 파일 접근 구성을 사용하세요.

SELinux를 사용하는 Linux 호스트라면 일반 소유권이 맞아도 레이블과 정책 때문에 접근이 거부될 수 있습니다. 예를 들어 getenforce와 ls -Zd /srv/myapp/data로 적용 상태와 레이블을 확인할 수 있습니다. Docker의 SELinux 레이블 안내는 z를 여러 컨테이너가 공유하는 용도, Z를 비공유 용도로 설명합니다. 호스트 레이블을 바꾸는 옵션이므로 앱 전용 경로와 배포 방식의 지원 여부를 확인해야 합니다.

원인을 모른 채 SELinux를 끄거나 /home·/usr 같은 큰 시스템 경로에 Z를 붙이지 않습니다. Docker Desktop은 Linux VM과 호스트 파일 공유를 거치므로 macOS·Windows에서도 이 Linux 권한 예시가 그대로 적용된다고 가정하지 마세요. 파일 공유 대상과 해당 환경의 접근 권한을 따로 확인합니다.

5. Compose 경로 오타를 조기에 찾고 수정 결과를 확인하세요

Compose volumes 문서의 긴 문법과 create_host_path: false를 사용하면 없는 경로가 자동 생성되어 원래 데이터 폴더로 착각하는 일을 줄일 수 있습니다. 아래는 기존에 만들어 둔 앱 전용 폴더를 연결하는 설정 조각입니다. user는 이미지가 해당 ID로 실행되도록 설계된 경우에만 지정하세요. 환경에 맞춘 이미지·나머지 서비스 설정은 별도로 필요합니다.

services:
  app:
    image: myapp:tested
    user: "10001:10001"
    volumes:
      - type: bind
        source: /srv/myapp/data
        target: /app/data
        read_only: false
        bind:
          create_host_path: false
  • 설정 변경 후 실제 컨테이너의 Source·Destination·RW·앱 ID 재확인
  • 앱이 쓰는 시험 파일로 생성·읽기·수정·삭제를 각각 확인
  • 컨테이너 재생성 후 파일이 유지되고 다른 작업이 실패하지 않는지 확인
  • 수정 전후의 오류 로그와 경로 소유권을 비교해 불필요한 변경 되돌리기

마운트 경로가 기존 이미지 안의 파일을 가리는 경우도 있으므로, 파일이 없다는 오류를 모두 권한 문제로 처리하지 마세요. 쓰기 오류 때문에 컨테이너가 반복 종료된다면 Docker Restarting 반복 점검도 함께 참고할 수 있습니다. 본문의 예시는 설명용이며 사용자의 Docker 호스트에서 실제 실행한 결과가 아닙니다.

6. 자주 묻는 질문

Docker 명령을 sudo로 실행하면 앱 파일 쓰기도 해결되나요?
데몬에 접근하는 사용자와 컨테이너 앱 프로세스의 파일 접근 조건은 다릅니다. 앱이 쓰는 경로와 실제 유효 ID를 확인해야 합니다.

chmod 777이면 해결되는데 그대로 둬도 되나요?
접근 범위가 넓어지고 SELinux·읽기 전용·ID 매핑 문제를 해결한 것도 아닐 수 있습니다. 확인한 원인에 맞춰 전용 사용자나 그룹의 필요한 권한으로 좁히세요.

일반 볼륨으로 바꾸면 권한 문제가 사라지나요?
Docker가 저장 위치를 관리해도 앱의 사용자와 파일 소유권은 확인해야 합니다. 저장 방식 변경은 데이터 이전과 복구 검증까지 포함해 판단해야 합니다.

확인 기준: 2026-10-03 Docker 공식 문서. Linux·Docker Desktop·rootless 환경을 구별하고 실제 배포 구성에 맞춰 적용하세요.