You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Django-React应用生产环境静态文件加载失败排查

Django-React容器化部署静态文件404问题

问题描述

本地运行正常,部署到ECS生产环境后静态文件返回404。已执行collectstatic命令,/vol/web/static目录下静态文件齐全,但浏览器请求https://site/static/js/main.db771bdd.js这类资源时仍返回404错误。


相关配置信息

Django settings.py 核心配置

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'build')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATIC_ROOT = '/vol/web/static'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'build', 'static')]

Nginx 代理配置

server {
    listen ${LISTEN_PORT};

    location /static {
        alias /vol/static;
    }

    location / {
        uwsgi_pass              ${APP_HOST}:${APP_PORT};
        include                 /etc/nginx/uwsgi_params;
        client_max_body_size    10M;
    }
}

API容器 Dockerfile

FROM python:3.9-alpine

ENV PYTHONUNBUFFERED 1
ENV PATH="/scripts:${PATH}"

RUN pip install --upgrade "pip<24.1"

COPY ./requirements.txt /requirements.txt
RUN apk add --update --no-cache postgresql-client jpeg-dev \
    && apk add --update --no-cache --virtual .tmp-build-deps \
       gcc libc-dev linux-headers postgresql-dev musl-dev zlib zlib-dev libffi-dev \
    && pip install -r /requirements.txt \
    && apk del .tmp-build-deps

RUN mkdir -p /app /vol/web/media /vol/web/static
RUN adduser -D user
RUN chown -R user:user /vol /app

COPY ./app /app
COPY ./scripts /scripts
COPY ./requirements.txt /requirements.txt

RUN chmod -R 755 /vol/web /app /scripts \
    && chmod +x /scripts/*

USER user
WORKDIR /app

VOLUME /vol/web

CMD ["entrypoint.sh"]

ECS任务容器挂载核心配置

  • API容器:将static卷挂载到/vol/web,通过entrypoint.sh执行collectstatic到/vol/web/static
  • Proxy容器:将static卷挂载到/vol/static,Nginx通过/static路径指向该目录

entrypoint.sh 启动脚本

#!/bin/sh

set -e
python manage.py collectstatic --noinput --settings=app.settings.staging
python manage.py wait_for_db --settings=app.settings.staging
python manage.py wait_for_es --settings=app.settings.staging
python manage.py migrate --settings=app.settings.staging
python manage.py search_index --rebuild --settings=app.settings.staging -f
uwsgi --socket :9000 --workers 4 --master --enable-threads --module app.wsgi --env DJANGO_SETTINGS_MODULE=app.settings.staging

排查方向与解决方法

1. 跨容器卷挂载路径不匹配

API容器把共享卷挂到/vol/web,静态文件收集后存放在/vol/web/static;但Proxy容器把同一份共享卷挂到了/vol/static,导致Proxy容器内的/vol/static实际对应API容器的/vol/web目录,而非/vol/web/static。

解决:二选一调整配置

  • 方案1:修改Proxy容器挂载路径为/vol/web,同时更新Nginx配置:
    location /static {
        alias /vol/web/static;
    }
    
  • 方案2:修改API容器的STATIC_ROOT为/vol/static,并调整API容器挂载路径为/vol/static,保持Nginx配置不变。

2. Nginx alias 路径拼接错误

使用alias时,路径末尾的斜杠会影响匹配逻辑:如果location是/static,alias路径为/vol/static,请求/static/js/xxx.js会被错误映射为/vol/staticjs/xxx.js。

解决:统一路径斜杠规则:

location /static/ {
    alias /vol/web/static/;
}

3. 共享卷类型不支持跨容器同步

ECS默认的空卷是容器本地卷,无法跨容器共享文件。需确认使用的是可共享卷类型(如Amazon EFS、绑定挂载到主机目录)。

验证:

  • 进入API容器执行ls /vol/web/static确认文件存在
  • 进入Proxy容器执行ls [对应挂载路径]/static确认文件同步

4. 静态文件权限不足

即使修改过权限,仍需确认Nginx进程用户(通常为nginx或www-data)对静态文件有读权限。

解决:在entrypoint.sh的collectstatic命令后添加权限修正:

chmod -R 644 /vol/web/static
chmod -R 755 /vol/web/static

5. 模板中静态文件路径硬编码

确保React构建后的index.html中静态文件引用使用Django的{% static %}标签生成,而非硬编码路径;若直接使用build目录作为模板,需保证src/href路径为/static/xxx,与STATIC_URL匹配。


调试命令

  • 查看Nginx错误日志:进入Proxy容器执行cat /var/log/nginx/error.log,可看到文件找不到的具体路径
  • 本地测试静态文件访问:在Proxy容器内执行curl http://localhost:8000/static/js/main.db771bdd.js
  • 查看ECS任务日志:通过AWS控制台查看API/Proxy容器日志,确认collectstatic执行状态、卷挂载是否报错

内容的提问来源于stack exchange,提问作者Lucas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:27:36