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
相关产品推荐
相关产品推荐

