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

Docker容器Volume失效,数据丢失问题(Django+PostgreSQL环境)

Django + Docker + PostgreSQL 数据持久化问题

我正在搭建Django + Docker + PostgreSQL环境,容器启动后执行docker exec -it <container_id> python manage.py createsuperuser创建超级用户并向数据库添加数据,但执行docker-compose stop后再启动容器,数据全部丢失,明明配置了Volume,为什么没生效?

相关配置文件

Dockerfile

FROM python:3.10.0-alpine
WORKDIR /usr/src/app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN pip install --upgrade pip
RUN apk update
RUN apk add postgresql-dev gcc python3-dev musl-dev
COPY ./requirements.txt .
RUN pip install -r requirements.txt
COPY ./entrypoint.sh .
RUN sed -i 's/\r$//g' /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh
COPY . .
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

docker-compose.yml

version: '3.9'
services:
  web:
    build: .
    command: gunicorn pets.wsgi:application --bind 0.0.0.0:8000
    expose:
      - 8000
    env_file:
      - .env
    depends_on:
      - db
  db:
    image: postgres:12.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - .env
  nginx:
    build: ./nginx
    ports:
      - 1337:80
    depends_on:
      - web
volumes:
  postgres_data:

entrypoint.sh

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

cd pets
python manage.py flush --no-input
python manage.py migrate

exec "$@"

问题原因

你的PostgreSQL Volume配置是正常的,数据丢失的根源在entrypoint.sh里的python manage.py flush --no-input命令——这个命令会强制清空数据库中的所有数据,并且不需要确认。每次容器启动时,entrypoint脚本都会执行这一步,所以哪怕PostgreSQL容器的Volume里保存了之前的数据,也会被flush命令清空。

解决方案

1. 直接移除flush命令(推荐)

修改entrypoint.sh,删掉python manage.py flush --no-input这一行,只保留数据库迁移命令:

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

cd pets
python manage.py migrate

exec "$@"

2. 仅在首次启动时执行初始化(如果需要测试数据)

如果你需要在项目首次启动时初始化测试数据,可以添加判断逻辑,只在数据库为空时执行flush或初始化脚本。比如检查某个核心表是否存在,不存在才执行初始化:

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

cd pets
# 检查auth_user表是否存在,不存在则执行初始化
python manage.py inspectdb auth_user > /dev/null 2>&1
if [ $? -ne 0 ]; then
    python manage.py flush --no-input
    python manage.py migrate
    # 可以在这里添加加载测试数据的命令,比如python manage.py loaddata fixtures/test_data.json
else
    python manage.py migrate
fi

exec "$@"

修改后重新构建镜像并启动容器,数据就能正常持久化了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:56:07