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

Docker容器中SQLite3写入失败:Django迁移报错求助

问题描述

我正尝试在EC2实例部署Django/React应用,本地Windows环境运行正常,但将代码部署到Ubuntu 22.04.3容器时出现以下错误:

django.db.migrations.exceptions.MigrationSchemaMissing: Unable to create the django_migrations table (attempt to write a readonly database)

请问这是Linux系统还是Dockerfile的问题?我原本计划熟练后改用PostgreSQL,是否现在就应该切换?

Dockerfile:

ARG PYTHON_VERSION=3.9-slim-bullseye
FROM python:${PYTHON_VERSION} as python


# Stage1:  Create Wheels
FROM python as python-build-stage
ARG BUILD_ENVIRONMENT=local

# required for make and setup for postgres (not used yet)
RUN apt-get update && apt-get install --no-install-recommends -y \
   build-essential \
   libpq-dev


COPY Backend/requirements .
 
RUN pip wheel --wheel-dir /usr/src/app/wheels \
   -r ${BUILD_ENVIRONMENT}.txt


# Stage 2:  Setup Django
FROM python as python-run-stage

ARG BUILD_ENVIRONMENT=local
ARG APP_HOME=/app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

ENV BUILD_ENV ${BUILD_ENVIRONMENT}

WORKDIR ${APP_HOME}

RUN addgroup --system django \
    && adduser --system --ingroup django django

RUN apt-get update && apt-get install --no-install-recommends -y \
    libpq-dev \
    netcat \
    && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
    && rm -rf /var/lib/apt/lists/*

COPY --from=python-build-stage /usr/src/app/wheels /wheels/

RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \
   && rm -rf /wheels/

# django app 
COPY --chown=django:django ./Webserver/django/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint
RUN chmod +x /entrypoint

COPY --chown=django:django ./Webserver/django/start /start
RUN sed -i 's/\r$//g' /start
RUN chmod +x /start

COPY --chown=django:django . ${APP_HOME}

RUN chown django:django ${APP_HOME}

USER django

ENTRYPOINT ["/entrypoint"]

entrypoint:

#!/bin/bash

set -o errexit
set -o pipefail
set -o nounset

exec "$@"

Start:

#!/bin/bash

set -o errexit
set -o pipefail
set -o nounset
 
python3 Backend/manage.py migrate --no-input
python3 Backend/manage.py collectstatic --no-input
sudo python3 Backend/manage.py runserver 0.0.0.0:8000
# sudo gunicorn finalstrip.wsgi:application --bind 0.0.0.0:8000  --timeout 600

问题分析与解决方案

错误根源

这个问题是Docker配置和启动脚本的问题,和Linux系统本身无关,核心原因有两点:

  1. sudo权限冲突:你在start脚本里用sudo执行服务,但容器内的django系统用户没有sudo权限,强制切换到root后,数据库文件的所有者变成root,后续django用户再操作时就会触发只读限制。
  2. SQLite路径权限:如果用默认的SQLite数据库,它的存储文件(默认是Backend/db.sqlite3)需要django用户有读写权限,sudo切换用户后会打破这个权限规则,导致无法写入。

修复步骤

1. 移除start脚本中的sudo

直接用django用户运行服务,删除sudo关键字:

#!/bin/bash

set -o errexit
set -o pipefail
set -o nounset
 
python3 Backend/manage.py migrate --no-input
python3 Backend/manage.py collectstatic --no-input
python3 Backend/manage.py runserver 0.0.0.0:8000
# python3 gunicorn finalstrip.wsgi:application --bind 0.0.0.0:8000  --timeout 600

2. 确保数据库目录权限

如果项目中已经存在db.sqlite3,在Dockerfile末尾添加权限配置,确保django用户能读写:

# 确保Django项目目录有读写权限
RUN mkdir -p ${APP_HOME}/Backend && chown django:django ${APP_HOME}/Backend

3. 容器内避免使用sudo

容器环境下尽量用非root用户直接运行服务,既符合安全规范,也能避免不必要的权限冲突。

是否现在切换到PostgreSQL?

建议立刻切换,理由如下:

  • SQLite不适合生产环境:它是单文件数据库,并发性能差,不支持多进程写入,而生产环境常用的Gunicorn是多进程模式,很容易出现锁死或读写错误。
  • 提前适配生产流程:现在切换可以提前解决数据库迁移、环境变量配置、权限等问题,避免后期从SQLite迁移到PostgreSQL时出现数据兼容或配置遗漏。
  • 你的Dockerfile已经预装了libpq-dev,已经为PostgreSQL做好了依赖准备,切换成本极低。

切换参考步骤:

  1. 在对应环境的依赖文件(比如requirements/local.txt)中添加psycopg2-binary
  2. 修改Django的settings.py数据库配置:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('POSTGRES_DB'),
        'USER': os.environ.get('POSTGRES_USER'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        'HOST': 'postgres', # 用Docker Compose时对应服务名,EC2部署则填实例IP
        'PORT': '5432',
    }
}
  1. 用Docker Compose编排PostgreSQL服务,或者在EC2实例上单独部署PostgreSQL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 01:27:44