我正在创建使用PostgreSQL数据库跟踪登录信息,uploaded/downloaded文件等的Django服务器的docker映像。即使在退出并重新启动docker映像时,我也希望数据库中的数据始终存在。

我创建了docker-compose文件和入口点文件,该文件和入口点文件成功启动了服务器docker映像并为数据库创建了一个卷。我在网上阅读的每个教程都说拥有持久性数据就像将数据库卷从要存储在主机上的位置映射到Docker映像中的/var/lib/postgresql/data位置一样简单。

docker-compose.yml:

version: '3.7'

services:
  web:
    build: ./
    command: python manage.py runserver 0.0.0.0:8000
    ports:
      - 8000:8000
    environment:
      - DEBUG=1
      - SECRET_KEY=foo
      - SQL_ENGINE=django.db.backends.postgresql
      - SQL_HOST=db
      - SQL_PORT=5432
      - DATABASE=postgres
    depends_on:
      - db
  db:
    image: postgres
    volumes:
      - ./postgres_data:/var/lib/postgresql/data/
    environment:
      ...
    ports:
      - 5432:5432

volumes:
  postgres_data:

docker-entrypoint.sh:

#!/bin/sh

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

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

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

exec $@

Dockerfile:

FROM python:3.7.4-alpine

ARG PROJECT=MyProject
ARG PROJECT_DIR=/var/www/${PROJECT}
RUN mkdir -p $PROJECT_DIR
WORKDIR $PROJECT_DIR

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apk update \
    && apk add --virtual build-deps gcc python3-dev musl-dev \
    && apk add postgresql-dev \
    && pip install psycopg2 \
    && pip install django \
    && pip install djangorestframework \
    && pip install django-sslserver \
    && pip install djangosecure \
    && pip install psycopg2 \
    && pip install django-environ \
    && apk del build-deps

COPY . $PROJECT_DIR/

ENTRYPOINT ["/var/www/EchoNine/docker-entrypoint.sh"]

settings.py

import os
import sys
from django.conf import settings
import environ

env = environ.Env(
    # set casting, default value
    DEBUG=(bool, False)
)

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

MEDIA_URL = 'inspections/'

TEST_ROOT = os.path.join(BASE_DIR, 'test')

if ('test' in sys.argv):
    MEDIA_ROOT = os.path.join(TEST_ROOT, 'inspections')
else:
    MEDIA_ROOT = os.path.join(BASE_DIR, 'inspections')

root = environ.Path(__file__) - 3 # three folder back (/a/b/c/ - 3 = /)
environ.Env.read_env(env.str('ENV_PATH', '.env.production')) # reading .env fil

SECRET_KEY = env('SECRET_KEY')

DEBUG = env('DEBUG') # This is set to False

ALLOWED_HOSTS = []

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'djangosecure',
    'sslserver',

    # Third-Party Apps
    'rest_framework',
    'rest_framework.authtoken',

    # Local Apps (Your project's apps)
    'MyProject.MyProject',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
}

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

MIDDLEWARE_CLASSES = (
    'djangosecure.middleware.SecurityMiddleware',
)

ROOT_URLCONF = 'MyProject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'MyProject.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': os.environ.get('SQL_ENGINE', 'django.db.backends.sqlite3'),
        'NAME': os.environ.get('SQL_DATABASE', os.path.join(BASE_DIR, 'db.sqlite3')),
        'USER': os.environ.get('SQL_USER', 'user'),
        'PASSWORD': os.environ.get('SQL_PASSWORD', 'password'),
        'HOST': os.environ.get('SQL_HOST', 'localhost'),
        'PORT': os.environ.get('SQL_PORT', '5432'),
    }
}

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

STATIC_URL = '/static/'

当我启动docker映像时,在docker映像(将数据存储在数据库中)内创建一个新的超级用户,退出docker映像,然后重新启动该映像,所有数据库表都再次为空。我希望数据库保留上一次运行时的数据库条目。

主机上的./postgres_data和docker映像内的/var/lib/postgresql/data似乎都使用文件和文件夹结构进行了初始化。

谁能告诉我我在做什么错?谢谢。

分析解答

您可以通过Entrypoints删除所有内容,因为入口点将从每个容器操作(start/restart)开始

PS:manage.py flush将删除您的所有数据