Docker中运行Django collectstatic触发[Errno 13]权限拒绝问题
解决Docker中Django collectstatic权限拒绝问题
问题重现
执行collectstatic命令时触发权限错误:
docker-compose exec web python manage.py collectstatic
错误日志片段:
Traceback (most recent call last): File "/code/manage.py", line 22, in <module> main() File "/code/manage.py", line 18, in main execute_from_command_line(sys.argv) File "/usr/local/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() ... PermissionError: [Errno 13] Permission denied: '/code/static/admin/img/tooltag-arrowright.bbfb788a849e.svg.gz'
当前配置文件
Dockerfile
# Pull base image FROM python:3.11.4-slim-bullseye # Set environment variables ENV PIP_NO_CACHE_DIR off ENV PIP_DISABLE_PIP_VERSION_CHECK 1 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 1 ENV COLUMNS 80 # Install Debian dependencies for Python apps RUN apt-get update \ && apt-get install -y --force-yes python3-pip ffmpeg git libmagic-dev libpq-dev gcc \ && rm -rf /var/lib/apt/lists/* # Set working directory WORKDIR /code/ # Install Python dependencies COPY requirements.txt . RUN pip install -r requirements.txt # Copy project files COPY . . # Create non-root user RUN useradd -m example-user # Create media/static directories and set permissions RUN mkdir -p /code/media /code/static && \ chown -R example-user:example-user /code/media /code/static # Set directory permissions RUN chmod -R 755 /code # Switch to non-root user USER example-user
docker-compose.yml
#version: "3.9" services: web: build: . command: gunicorn mysite.wsgi -b 0.0.0.0:8000 --reload volumes: - .:/code ports: - 8000:8000 depends_on: - db - redis - celery environment: - "DJANGO_SECRET_KEY=scret_key" - "DJANGO_DEBUG=True" - "DJANGO_SECURE_SSL_REDIRECT=False" - "DJANGO_SECURE_HSTS_SECONDS=0" - "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS=False" - "DJANGO_SECURE_HSTS_PRELOAD=False" - "DJANGO_SESSION_COOKIE_SECURE=False" - "ACCESS_KEY_ID=scret_id" - "SECRET_ACCESS_KEY=scret_key" - "STORAGE_BUCKET_NAME=bucket" - "S3_CUSTOM_DOMAIN=domain" - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 user: example-user db: image: postgres:13 volumes: - postgres_data:/var/lib/postgresql/data/ environment: - "POSTGRES_HOST_AUTH_METHOD=trust" redis: image: redis:6 ports: - 6379:6379 celery: build: . command: celery -A mysite worker --loglevel=info volumes: - .:/code depends_on: - redis - db environment: - "DJANGO_SECRET_KEY=scret_key" - "DJANGO_DEBUG=True" - "DJANGO_SECURE_SSL_REDIRECT=False" - "DJANGO_SECURE_HSTS_SECONDS=0" - "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS=False" - "DJANGO_SECURE_HSTS_PRELOAD=False" - "DJANGO_SESSION_COOKIE_SECURE=False" - "ACCESS_KEY_ID=scret_id" - "SECRET_ACCESS_KEY=scret_key" - "STORAGE_BUCKET_NAME=name" - "S3_CUSTOM_DOMAIN=domain" - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 user: example-user volumes: postgres_data:
排查结果
执行docker-compose exec web ls -l /code/static后确认,static目录下除staticfiles.json外,其余文件/目录的属主均为root:
total 16 drwxrwxrwx 1 root root 4096 Apr 5 05:42 admin drwxrwxrwx 1 root root 4096 Sep 21 22:36 css drwxrwxrwx 1 root root 4096 Sep 21 22:36 human drwxrwxrwx 1 root root 4096 Sep 18 18:42 img -rw-r--r-- 1 user-mani user-mani 13091 Sep 21 22:36 staticfiles.json drwxrwxrwx 1 root root 4096 Sep 21 22:36 transcribe
解决方案
核心原因
Docker Compose中挂载的本地目录./覆盖了容器内/code目录的权限设置,本地static目录的文件由root创建,容器内非root用户example-user无写入权限。
修复步骤
调整Dockerfile权限设置顺序
将目录创建、权限设置放到项目文件复制之后,确保容器内文件属主正确:# Create non-root user RUN useradd -m example-user # Copy project files COPY . . # Create media/static directories if not exist RUN mkdir -p /code/media /code/static # Grant ownership to non-root user RUN chown -R example-user:example-user /code # Set proper read/write permissions RUN chmod -R 755 /code/media /code/static解决挂载目录权限冲突
- 方法一:同步本地与容器用户UID/GID
先查询容器内example-user的UID:
然后在本地主机执行:docker-compose exec web id -u example-usersudo chown -R <查询到的UID>:<查询到的GID> ./static ./media - 方法二:使用Docker命名卷挂载static/media
修改docker-compose.yml,将static和media目录单独挂载为命名卷:
此方式下,static/media目录使用Docker管理的存储,容器内权限设置会正常生效。services: web: # ...其他配置 volumes: - .:/code - static_volume:/code/static - media_volume:/code/media # ...其他配置 volumes: postgres_data: static_volume: media_volume:
- 方法一:同步本地与容器用户UID/GID
临时应急方案
若需快速解决,可临时以root身份执行命令并修正权限:docker-compose exec -u root web python manage.py collectstatic docker-compose exec -u root web chown -R example-user:example-user /code/static
内容的提问来源于stack exchange,提问作者tthheemmaannii
相关产品推荐
相关产品推荐

