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

Docker-Compose构建Django项目时上传图片丢失问题求助

解决Docker中Django上传图片丢失的问题

我来帮你理清这个问题:你遇到的图片丢失情况,核心原因是图片没有被持久化存储到正确的Docker卷中,或者你的卷配置和项目配置存在冲突。

问题根源分析

从你的docker-compose.yml来看,虽然你给mediafiles目录挂载了web-static卷,但有几个潜在问题:

  1. 你把整个项目根目录/usr/src/app挂载到了web-django卷——这在开发模式下会导致镜像更新的代码被卷中旧内容覆盖,更关键的是,如果你的Django项目中MEDIA_ROOT配置的路径和挂载路径不匹配,图片会被存在容器内部而非卷里,容器重建后就会丢失。
  2. celery-beat服务使用的镜像名是citc_web,而其他服务是project_web,这是笔误,会导致镜像不一致(不过和图片丢失无关)。
  3. 你没有在web服务中配置媒体文件的访问路由(这会导致无法访问而非文件丢失,属于次要问题)。

具体解决方案

1. 修正Docker Compose卷配置

调整docker-compose.yml,确保媒体文件的卷挂载正确,同时避免项目根目录卷覆盖代码(开发模式下建议挂载本地代码目录而非named volume,生产模式则不需要挂载代码到卷):

version: '3'

volumes:
  web-static:  # 专门用于存储媒体文件的持久化卷
  redis-data:  # 给redis添加持久化卷(可选,防止redis数据丢失)

services:
  redis:
    image: "redis:alpine"
    volumes:
      - redis-data:/data  # 持久化redis数据
  web:
    build: .
    image: project_web
    command: python manage.py runserver 0.0.0.0:8000
    restart: always
    volumes:
      # 开发模式:挂载本地代码目录到容器,实时同步代码修改(替代原来的web-django卷)
      - .:/usr/src/app
      # 挂载媒体文件目录到专用卷,确保持久化
      - web-static:/usr/src/app/media
    ports:
      - "8000:8000"
    depends_on:
      - redis
  celery:
    image: project_web
    command: celery -A project_name worker -l info
    restart: always
    volumes:
      # 同样挂载媒体卷,确保celery能访问上传的文件
      - web-static:/usr/src/app/media
    depends_on:
      - web
      - redis
  celery-beat:
    image: project_web  # 修正镜像名称,和其他服务保持一致
    command: celery -A project_name beat -l info
    restart: always
    volumes:
      - web-static:/usr/src/app/media
    depends_on:
      - web
      - redis

2. 确认Django项目配置

在你的Django项目settings.py中,确保媒体文件的路径配置正确:

# settings.py
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 媒体文件核心配置
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

同时,在项目根urls.py中添加媒体文件的访问路由(开发模式下):

# urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
    # 你的其他业务路由...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

3. 验证持久化是否生效

修改配置后,按以下步骤操作:

  1. 清理旧的容器和卷(如果之前的卷已经存在异常):
    docker-compose down -v
    
  2. 重新构建并启动服务:
    docker-compose up --build
    
  3. 上传一张测试图片,然后执行docker-compose down再docker-compose up,检查图片是否还能正常访问。

关键注意点

  • 不要把整个项目根目录挂载到named volume:开发模式下挂载本地代码目录即可,生产模式下代码应该打包进镜像,不需要挂载卷。
  • 所有需要访问媒体文件的服务(比如celery)都要挂载同一个媒体卷:否则celery无法处理上传的文件。
  • 谨慎使用docker-compose down -v:这个命令会删除所有named volume,导致存储的图片永久丢失,除非你确定要清空所有持久化数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:40:52