Docker를 활용해 CI/CD 환경을 구축할 때, Jenkins 데이터를 영구적으로 보관하기 위해 호스트 디렉토리를 볼륨으로 마운트하는 것은 필수적입니다. 하지만 이 과정에서 많은 개발자들이 Jenkins Docker 권한 문제 해결에 어려움을 겪곤 합니다. Jenkins가 마운트된 디렉토리에 파일을 쓰지 못해 플러그인 설치가 실패하거나, 설정이 저장되지 않는 등의 문제가 발생하기 때문입니다.
이번 포스팅에서는 로그 파일에 가득 찬 java.nio.file.FileSystemException: ... Operation not permitted에러의 근본적인 원인을 파헤치고, 이를 해결하기 위한 확실한 방법들을 단계별로 알아보겠습니다. 이 가이드를 통해 골치 아픈 권한 문제에서 벗어나 안정적인 Jenkins 환경을 구축해 보시길 바랍니다.
1. 문제 상황: “Operation not permitted” 에러의 등장
Jenkins 컨테이너를 실행하고 호스트의 특정 경로를 /var/jenkins_home으로 마운트했습니다. 설레는 마음으로 Jenkins 초기 설정을 진행하려는데, 로그 창에 다음과 같은 붉은색 에러 메시지들이 폭포수처럼 쏟아집니다.
[ 주요 에러 로그 예시 ]
Also: java.nio.file.FileSystemException: /var/jenkins_home/plugins/json-api/META-INF/MANIFEST.MF: Operation not permitted
at java.base/sun.nio.fs.UnixException.translateToIOException(Unknown Source)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source)
...
at java.base/java.nio.file.Files.setPosixFilePermissions(Unknown Source)
at jenkins.util.io.PathRemover.makeWritable(PathRemover.java:283)
...
Also: java.nio.file.FileSystemException: /var/jenkins_home/plugins/json-api/META-INF/maven/io.jenkins.plugins/json-api/pom.xml: Operation not permitted
...
이 에러 메시지들의 핵심은 명확합니다. Jenkins 애플리케이션이 컨테이너 내부에 마운트된 볼륨 디렉토리(/var/jenkins_home)에 파일이나 디렉토리를 생성, 수정, 삭제할 권한이 없다는 것입니다. 이로 인해 플러그인 압축 해제나 설정 파일 생성이 불가능해져 Jenkins가 정상적으로 동작하지 않게 됩니다.
2. 원인 분석: 호스트와 컨테이너의 ID 불일치
Jenkins Docker 권한 문제 해결을 위해서는 Docker의 파일 시스템 작동 방식을 이해해야 합니다. 이 문제의 근본적인 원인은 호스트 시스템의 파일 소유권과 컨테이너 내부에서 실행되는 프로세스의 사용자 ID(UID)가 서로 다르기 때문입니다.

- 컨테이너 내부 실행 사용자 (jenkins: 1000): 보안상의 이유로 공식
jenkins/jenkinsDocker 이미지는root가 아닌jenkins라는 일반 사용자로 프로세스를 실행하도록 설정되어 있습니다. 이jenkins사용자의 기본 사용자 ID(UID)와 그룹 ID(GID)는 보통1000입니다. - 호스트 디렉토리의 소유권 (root: 0): Docker에서
-v /host/path:/container/path옵션으로 호스트 디렉토리를 마운트할 때, 만약 호스트에 해당 경로의 디렉토리가 없다면 Docker 데몬이 이를 자동으로 생성합니다. 이때 생성된 디렉토리의 소유권은 Docker 데몬을 실행하는 호스트의root사용자(UID 0)가 가지게 됩니다. - 권한 충돌 발생: 결과적으로 컨테이너 내부의
jenkins사용자(UID 1000)가 호스트의root사용자(UID 0) 소유인 디렉토리에 쓰기 작업을 시도하게 됩니다. 리눅스 커널은 이를 보안 위반으로 간주하고 접근을 차단하여 “Operation not permitted” 권한 오류를 발생시키는 것입니다.
3. Jenkins Docker 권한 문제 해결 솔루션
이러한 ID 불일치 문제를 해결하고 Jenkins에 올바른 권한을 부여하는 4가지 실질적인 방법을 소개합니다. 상황에 맞춰 가장 적합한 방법을 선택하시기 바랍니다.
방법 1: 호스트 디렉토리의 소유권 변경 (가장 신속한 해결)
가장 직관적이고 빠르게 문제를 해결할 수 있는 방법은 호스트 머신에서 마운트할 디렉토리의 소유권을 컨테이너 내부의 jenkins 사용자 ID와 일치시켜주는 것입니다.
Bash
# /path/to/jenkins_home은 실제 호스트의 데이터 디렉토리 경로로 변경해야 합니다.
# 1000:1000은 Jenkins 공식 이미지의 기본 UID:GID입니다.
sudo chown -R 1000:1000 /path/to/jenkins_home
이 명령어를 실행하면 호스트 디렉토리의 주인이 UID 1000번 사용자로 변경되므로, 컨테이너 내부의 jenkins사용자도 자유롭게 접근할 수 있게 됩니다.
방법 2: 컨테이너 시작 시 root로 권한 수정 (임시 해결)
컨테이너를 실행할 때 일시적으로 root 권한을 획득하여 볼륨 디렉토리의 소유권을 수정한 뒤 Jenkins를 실행하는 방법입니다.
- Docker 실행 시
--user root옵션을 추가하여root사용자로 컨테이너를 시작합니다.Bashdocker run -d --name jenkins \ -p 8080:8080 -p 50000:50000 \ -v /path/to/jenkins_home:/var/jenkins_home \ --user root \ jenkins/jenkins:lts - 실행된 컨테이너 내부에 접속하여
/var/jenkins_home디렉토리의 소유권을 변경합니다.Bashdocker exec -it jenkins bash # --- 컨테이너 내부 접속 후 실행 --- chown -R jenkins:jenkins /var/jenkins_home exit # -------------------------------- - (선택 사항) 권한 수정이 완료되었으므로 컨테이너를 중지 후 다시 시작하면, 기본 사용자인
jenkins로 실행되더라도 정상적으로 동작합니다. 하지만 컨테이너를 재생성할 때마다 이 과정을 반복해야 하는 불편함이 있습니다.
방법 3: Dockerfile을 이용한 초기화 (운영 환경 권장)
운영 환경에서는 커스텀 이미지를 빌드하여 이미지 자체에 초기화 로직을 포함시키는 것이 가장 깔끔하고 안정적인 Jenkins Docker 권한 문제 해결 방법입니다.
Dockerfile
# Dockerfile 작성
FROM jenkins/jenkins:lts
# 일시적으로 root 사용자로 전환하여 권한 설정 작업 수행
USER root
# Jenkins 홈 디렉토리를 생성하고 소유권을 jenkins 사용자로 변경
RUN mkdir -p /var/jenkins_home && \
chown -R jenkins:jenkins /var/jenkins_home
# 보안을 위해 다시 jenkins 사용자로 전환하여 컨테이너 실행
USER jenkins
이 Dockerfile로 빌드된 이미지는 컨테이너 시작 시점에 항상 올바른 권한을 갖도록 보장합니다.
방법 4: Docker Compose 사용 시 user 지정
Docker Compose를 사용하여 인프라를 관리한다면 docker-compose.yml 파일에서 user 속성을 통해 컨테이너가 실행될 UID/GID를 명시적으로 지정하여 충돌을 방지할 수 있습니다.
YAML
version: '3.8'
services:
jenkins:
image: jenkins/jenkins:lts
# 호스트 디렉토리의 소유자 ID와 일치하는 UID:GID를 지정합니다.
# 예: 호스트의 현재 사용자가 UID 1000인 경우
user: "1000:1000"
volumes:
- /path/to/jenkins_home:/var/jenkins_home
ports:
- "8080:8080"
- "50000:50000"
4. 권한 문제 해결 확인 및 결론
위 방법들을 적용한 후 컨테이너가 정상적으로 실행되었다면, 컨테이너 내부에서 디렉토리 권한이 올바르게 변경되었는지 최종적으로 확인해 봅니다.
Bash
docker exec -it <container_name> ls -l /var
출력 결과에서 jenkins_home 디렉토리의 소유자가 jenkins (또는 지정한 UID)로 되어 있다면 권한 문제가 완벽하게 해결된 것입니다.
Bash
drwxr-xr-x 15 jenkins jenkins 4096 Oct 25 08:00 jenkins_home
지금까지 Docker 환경에서 빈번하게 발생하는 Jenkins Docker 권한 문제 해결 방법에 대해 알아보았습니다. 호스트 경로를 직접 마운트하는 방식(Bind Mount)은 이처럼 권한 관리가 까다로울 수 있습니다.
베스트 프랙티스: 가능하다면 호스트 경로 직접 마운트 대신 Docker가 관리하는 Docker Named Volume을 사용하는 것을 권장합니다.
Bash
# Docker가 관리하는 볼륨 생성 및 사용
docker volume create jenkins_data
docker run -d --name jenkins -v jenkins_data:/var/jenkins_home ...
이 방식을 사용하면 Docker가 알아서 적절한 권한으로 볼륨을 마운트해주므로 복잡한 권한 설정 없이도 문제를 예방할 수 있습니다. 이 가이드가 여러분의 안정적인 CI/CD 환경 구축에 도움이 되기를 바랍니다.