글작성시 이미지 업로드 고질병 해결기
댓글 1
포스트 내용에 대한 의견이나 질문을 남길 수 있습니다. 답글과 좋아요는 로그인한 사용자 기준으로 기록됩니다.
이전 글과 다음 글
현재 글을 기준으로 앞뒤 글을 바로 이동해서 볼 수 있습니다.
Loading Services...
포스트 내용에 대한 의견이나 질문을 남길 수 있습니다. 답글과 좋아요는 로그인한 사용자 기준으로 기록됩니다.
현재 글을 기준으로 앞뒤 글을 바로 이동해서 볼 수 있습니다.

증상: 간헐적으로 글작성하다가 이미지를 업로드하면 엑박이 되어서 퀼 에디터에 보임. 원래도 이미지 처리 방식이나 제한을 둬서 과거에 많이 픽스를 마니 했음. 근데 한동안 안그러다 이번에 또그러는거. 결론만 말하면 post 200 뜬거 네트워크탭에서 확인했고 근데 업로드한걸 불러오는게 404뜸. vscode같은 에디터로 ssh 접속해서 미디어디렉토리 보는데 post나 404 경로는 ../2025/12/5 인데 에디터 상에는 폴더 자체가 /2025/12 까지만 만들어져있음. 나는 멍청하게도 도커를쓰면서 소스코드도 서버에 두고 바인드마운트 운영하는데, 이해가안감 그래서 도커 내부 ls 로 보니까 12/5까지 있음. 아 ㅇㅇ 권한문제생기면 보이지도 않을수도 있구나. 호스트 터미널로 직접 12/5까지 들어갔어야했는데 gui로 그냥 보고 왜없지? 이런거임. 아무튼 아래는 ai설명작성이라 그냥 대충 해결과정 저리 했구나 하시면댐. 간혈적인건 아마 11월에 글 마지막으로 쓰고 12월에 올만에 써서 도커루트가 12월의 5일 디렉토리 만들었는데 12까지는 아마 호스트도 접근가능한데 5일이 도커 루트사용자꺼라 nginx랑 호스트가 접근못한듯 그래서 post 200인데 콜하면 404. 11월이나 이전엔 왜 괜찮았냐고? 그땐 도커 한동안 안녀려서 문제 안생겼거나 예전에 고쳤는데 까먹은듯.
Django Docker 환경에서 이미지 업로드 후 404가 발생한 문제는 파일이 없어서가 아니라, 컨테이너 안의 root가 700 권한으로 디렉토리를 만들어 호스트와 Nginx가 접근할 수 없었기 때문입니다. Non-root 사용자(app) + www-data 그룹 + 호스트 권한 조정으로 완전히 해결했습니다.
핵심 설명1단계: 겉보기 원인 찾기 (URL, 설정 확인)문제: Quill 에디터에서 이미지 업로드 후 404 오류
확인한 것:
Django URL 설정: /upload_image/ → blog.views.upload_image ✅ 정상
Django 파일 저장 경로: settings.py의 MEDIA_ROOT, MEDIA_URL ✅ 정상
Nginx 설정: /media/ → /home/ds/project/server/django/media/ 매핑 ✅ 정상결론: 표면적인 설정은 모두 맞는데 파일이 안 보임
2단계: "어? 파일이 진짜 없잖아?" 진짜 문제 발견확인 방법:
# 호스트에서 폴더 접근 시도 ls -la /home/ds/project/server/django/media/2025/12/5/ # 출력: Permission denied ❌
발견: 파일이 없는 게 아니라 접근 권한이 없었음
3단계: "범인은 root였다!" 근본 원인 파악컨테이너 내부 확인:
docker exec server-django-1 ls -la /app/media/2025/12/5/ # 출력: drwx------ root root (700 권한)
정체: Django 컨테이너가 root 사용자로 실행되면서, 이미지 업로드 때 os.makedirs()로 만든 디렉토리가 모두 root:root 700 권한이었음. 볼륨 마운트 때문에 호스트에도 그대로 적용되어, ds 계정과 Nginx(www-data)가 접근 불가능했음
4단계: "새 문제, 새 해결" 권한 충돌 해결첫 번째 시도: Dockerfile에서 root 대신 app 사용자로 실행
→ 새로운 에러: 로그 파일(admin_activity.log)에 쓸 권한 없음 ❌
원인: app 사용자는 media에는 접근 가능하지만, logs 폴더는 아직 권한이 맞지 않음
5단계: "완전한 해결" 3가지 조정① Dockerfile 수정 (app 사용자 생성 + www-data 그룹 추가)
RUN groupadd -g 33 www-data-group 2>/dev/null || true && \
useradd -m -u 1000 -g 33 app
USER app
② 호스트 권한 조정 (media, logs 폴더 소유권·권한 맞추기)
# media와 logs 디렉토리를 ds:www-data로 변경 sudo chown -R ds:www-data /home/ds/project/server/django/media sudo chown -R ds:www-data /home/ds/project/server/django/logs # 권한을 775로 설정 (소유자·그룹 모두 쓰기 가능) sudo chmod -R 775 /home/ds/project/server/django/media sudo chmod -R 775 /home/ds/project/server/django/logs # Nginx 재시작 sudo systemctl restart nginx
③ docker-compose.yml에 UID/GID 명시
build:
context: ./django
args:
UID: 1000
GID: 33
예시권한 변화 흐름
테스트로 확인하기# 1. 컨테이너 사용자 확인 docker exec server-django-1 id # 출력: uid=1000(app) gid=33(www-data) groups=33(www-data) ✅ # 2. 파일 생성 테스트 docker exec server-django-1 touch /app/media/test.txt ls -la /home/ds/project/server/django/media/test.txt # 출력: -rw-r--r-- ds www-data ✅ # 3. 이미지 업로드 테스트 # Quill 에디터에서 이미지 업로드 → 404 없이 정상 로드 ✅
체크리스트 Dockerfile에서 non-root 사용자(app) 생성
app 사용자를 www-data 그룹(GID 33)에 추가
호스트의 media, logs 디렉토리 소유권을 ds:www-data로 변경
호스트의 media, logs 디렉토리 권한을 775로 변경
docker-compose.yml에 UID/GID 빌드 인자 추가
Nginx 재시작 및 이미지 업로드 재테스트
새로운 날짜 디렉토리가 생성되어도 권한 문제 없는지 확인
| 단계 | 소유자 | 권한 | 문제 |
|---|---|---|---|
| ❌ 처음 (root 사용자) | root:root | 700 | 아무도 접근 못함 |
| ⚠️ 중간 시도 (app 사용자) | app:? | 755 | logs 폴더는 여전히 권한 오류 |
| ✅ 최종 (호스트 조정) | ds:www-data | 775 | Django·Nginx·호스트 모두 접근 가능 |
테스트로 확인하기# 1. 컨테이너 사용자 확인 docker exec server-django-1 id # 출력: uid=1000(app) gid=33(www-data) groups=33(www-data) ✅ # 2. 파일 생성 테스트 docker exec server-django-1 touch /app/media/test.txt ls -la /home/ds/project/server/django/media/test.txt # 출력: -rw-r--r-- ds www-data ✅ # 3. 이미지 업로드 테스트 # Quill 에디터에서 이미지 업로드 → 404 없이 정상 로드 ✅
체크리스트 Dockerfile에서 non-root 사용자(app) 생성
app 사용자를 www-data 그룹(GID 33)에 추가
호스트의 media, logs 디렉토리 소유권을 ds:www-data로 변경
호스트의 media, logs 디렉토리 권한을 775로 변경
docker-compose.yml에 UID/GID 빌드 인자 추가
Nginx 재시작 및 이미지 업로드 재테스트
새로운 날짜 디렉토리가 생성되어도 권한 문제 없는지 확인