Приветствую всех!
Я начинающий разработчик и хочу поделиться своим решением проблемы, с которой столкнулся и не нашел готового решения в интернете. Мой подход может не быть оптимальным, но может быть полезен другим новичкам.
Предполагаю, что если вы нашли эту статью, то уже знакомы с процессом установки Docker и использования Django, поэтому не буду расписывать их детально. Но у вас уже должен быть установлен Docker.
Я работаю на windows, поэтому если у вас другая операционная система, то команды могут отличаться.
Шаг 1
Самый сложный.
Создаем рабочую папку.
Шаг 2
Создаем или сразу запускаем виртуальное окружение если оно у вас есть.
Создаем:
В терминале переходим в рабочую папку, которую только что создали. Переход выполняется посредством команды cd и путь к вашей папке.
Пример:C:\Users\User>cd C:\TestДалее, находясь в рабочий папке, введите так же в терминале, команду для создания виртуального окружения: python -m venv +---> (название)Пример: C:\Test>python -m venv myenv
Активируем:
В терминале пишем путь до папки ScriptsПример:C:\Test>cd C:\Test\myenv\ScriptsЗатем прописываем команду activate, которая и активируем наше виртуальное окружение.
Пример:C:\Test\myenv\Scripts>activateЕсли вы сделали правильно, то успешная активация виртуального окружения будет выглядеть следующим образом:(myenv) C:\Test\myenv\Scripts>Как можете заметить, вначале строки появилось название виртуального окружения в скобках. 
Шаг 3
Возвращаемся в корневую папку проекта (Шаг 1)
Пример:(myenv) C:\Test\myenv\Scripts>cd C:\Test
Создаем файл requirements.txt, в  терминале пишите команду:pip freeze > requirements.txt  
После чего в вашей директории появится файл requirements.txt ,в котором будут отображаться ваши установленные пакеты и зависимости. На данном этапе, если вы начинали проект с самого начала вместе со мной, то этот файл у вас будет пустой.
Шаг 4
Устанавливаем пакеты, в терминале пишем следующие команды:python -m pip install Django - устанавливаем фреймворк Django с помощью менеджера пакетов pip в Python.
Пример:(myenv) C:\Test>python -m pip install Django 
Далее пишем другую команду в терминале:pip install psycopg2-binary - библиотека psycopg2-binary предоставляет Python-интерфейс для работы с СУБД PostgreSQL.  
Пример:(myenv) C:\Test>pip install psycopg2-binaryПосле установки, обновляем requirements.txt  посредством уже известной нам команды:pip freeze > requirements.txtТеперь в файле requirements.txt, должны отображаться ваши установленные пакеты. 
Шаг 5
Создаем новый проект Django в корневой директории (Шаг 1) с заданным названием. 
 docker-compose run django django-admin startproject (название) .Не забудь про точку в конце команды.(myenv) C:\Test>docker-compose run django django-admin startproject testpostgre .
Далее:
Cоздаем новое Django приложение в корневой директории  с новым названием.python manage.py startapp (название)
Пример:(myenv) C:\Test\testpostgre>python manage.py startapp app
Далее:
Переносим вручную файл manage.py в корневую директорию (папка из шага 1)
Шаг 6
Открываем свой IDE, и в корневой директории (в папке из "Шаг 1") создаем два файла:
- Dockerfile (название файла) 
# Используем официальный образ Python в качестве базового образа
FROM python
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /usr/src/app
# Копируем файл requirements.txt внутрь контейнера
COPY requirements.txt ./
# Устанавливаем зависимости, описанные в файле requirements.txt
RUN pip install -r requirements.txt- docker-compose.yml (название файла) 
# Определение версии Docker Compose и начало описания сервисов
version: '3'
services:
  django:
    # Сборка образа для сервиса django из текущей директории
    build: .
    # Задание имени контейнера для сервиса django
    container_name: django
    # Задание команды, которую нужно запустить при запуске контейнера для сервиса django
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/usr/src/app
    # Открытие порта на хостовой машине и перенаправление на порт в контейнере
    ports:
      - 8000:8000
    # Зависимость от другого сервиса
    depends_on:
      - pgdb
  pgdb:
    # Использование готового образа postgres
    image: postgres
    # Задание переменных окружения для контейнера с postgres
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
     # Задание имени контейнера для сервиса pgdb
    container_name: pgdb
     # Связывание тома с директорией в контейнере для сохранения данных postgres
    volumes:
      - pgdbdata:/var/lib/postgresql/data/
volumes:
  pgdbdata: null
Таким образом структура вашего проекта должна выглядеть примерно так:

Шаг 7
Открываем файл settings.pyи меняем там следующие строки кода:
Так было:
ALLOWED_HOSTS = []
Так стало:
# Определяем список разрешенных хостов для доступа к приложению
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0']Далее спускаемся ниже по коду:
Так было:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
    
Так стало:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app', # Добавляем наше приложение из "Шаг 5"
    'django.contrib.postgres', #это модуль Django, который предоставляет интеграцию с базой данных PostgreSQL 
]Далее меняем следующие строки:
Так было:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
Так стало:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',   # Используется PostgreSQL
        'NAME': 'postgres', # Имя базы данных
        'USER': 'postgres', # Имя пользователя
        'PASSWORD': 'postgres', # Пароль пользователя
        'HOST': 'pgdb', # Наименование контейнера для базы данных в Docker Compose
        'PORT': '5432',  # Порт базы данных
    }
}Шаг 8
Переходим в файл models.py и создаем там модель для теста БД.
# Импорт модуля models из библиотеки Django
from django.db import models
# Определение класса MyModel, который наследует модель Django Model
class MyModel(models.Model):
    # Определение поля id типа AutoField как первичного ключа
    id = models.AutoField(primary_key=True)
    # Определение поля phone типа CharField с максимальной длиной в 20 символов
    phone = models.CharField(max_length=20)
    # Определение метода __str__, который будет использоваться для представления экземпляров модели в виде строки
    def __str__(self):
        return self.phone
Далее открываем файл admin.py и регистрируем созданную нами модель в админ-панели Django:
# Импорт модуля admin из библиотеки Django.contrib
from django.contrib import admin
# Импорт модели MyModel из текущего каталога (".")
from .models import MyModel
# Регистрация модели MyModel для административного сайта
admin.site.register(MyModel)Шаг 9
Запускает все сервисы, определенные в файле docker-compose.yml в текущей директории, в режиме detached (фоновый режим) с помощью команды в терминале:docker-compose up
Пример:C:\Test> docker-compose up
Далее:
Открываем браузер и переходим по адресу http://localhost:8000/
И если вы всё правильно запустили, то вас будет ждать там следующая картина:

Далее:
Производите миграцию, выполнив команду в терминале:docker-compose run django python manage.py migrateПример:C:\Test> docker-compose run django python manage.py migrate
Далее:
Создаем супер-пользователя для входа в админ-панель:
В терминале, находясь в папке (Шаг 1) пишем следующую команду:docker-compose run django python manage.py createsuperuserПример:C:\Test> docker-compose run django python manage.py createsuperuserЗатем вам нужно ввести имя пользователя:Username (leave blank to use 'root'): - вводите любое имя латинице
После будет поле Email:Email address: - можете вводить или пропустить нажав Enter
Далее поле с паролем, сразу учтите, при вводе пароля, он отображаться не будет, не пугайтесь. Как ввели пароль, нажмите Enter, и потом повторите пароль ещё раз.Password:Если вы введете легкий пароль, то вас спросят:
Password (again):Bypass password validation and create user anyway? [y/N]: - введите "y" и нажмите Enter
Строка Superuser created successfully. означает что вы все сделали правильно.
Далее:
Поднимаете ваши контейнера, с помощью команды docker-compose upПример: C:\Test> docker-compose up
Открываете браузер и переходите по адресу: http://localhost:8000/admin
Должны увидеть следующее:

Вводите имя пользователя и пароль, которые только что создали.
Нажимаем на My models (или как вы назвали свой класс в "Шаг 8")

Добавляете несколько данных для проверки работоспособности.
Шаг 10
Входим в интерактивный режим Postgres внутри контейнера Docker.
Для этого нужно прописать следующую команду в терминале:docker exec -it <имя_контейнера> psql -U <имя_пользователя> <имя_базы_данных>  
Пример:docker exec -it pgdb psql -U postgres postgres  
Чтобы посмотреть таблицы в PostgreSQL из интерактивного режима psql, вы можете выполнить команду \dt;, которая выведет список всех таблиц в текущей базе данных.  
Пример:postgres=# \dt;
Получаем список всех таблиц в нашей базе данных:

Для того, чтобы посмотреть данные в таблице app_mymodel, необходимо выполнить следующую команду:  SELECT * FROM app_mymodel;  
Ну вот и всё, теперь у вас в контейнере Docker запущен Django и PostgreSQL.
Бонус
Если перейти по ссылке https://hub.docker.com/_/postgres
И скопировать текст команды docker pull postgres

То, эта команда запустит процесс загрузки (pull) образа Docker для СУБД PostgreSQL из официального репозитория Docker Hub.
Для этого вставьте скопированный текст в терминал.
Пример:(dtenv)C:\Docker_Test> docker pull postgres
После того, как процесс загрузки завершится, образ будет доступен локально на вашей машине и вы сможете использовать его для создания и запуска контейнеров PostgreSQL в вашей среде.
Затем меняем немного код в файле docker-compose.yml
version: '3'
services:
  django:
    build: .
    container_name: django
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/usr/src/app
    ports:
      - 8000:8000
    depends_on:
      - pgdb
  pgdb:
    image: postgres
    restart: always
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    container_name: pgdb
    volumes:
      - pgdbdata:/var/lib/postgresql/data/
  adminer:
    image: adminer
    restart: always   #c 26 по 30 строку(вставлен новый фрагмент)
    ports:
      - 8080:8080
volumes:
  pgdbdata: nullВновь выполняем команду сборки docker-compose upПример:(dtenv)C:\Docker_Test> docker-compose up
После проделанных манипуляций, можем перейти по адресу http://127.0.0.1:8080/
И увидеть там вход в БД:

В разделе "Движок" меняете MySQL на PostgreSQL, в разделе "Сервер" пишите название Хоста указанного у вас в файле settings.py, если не можете найти, то посмотрите на картинку:

Далее вводите Имя пользователя и Пароль что вы указали, или если делали как я, то указывайте тоже самое. Название БД вводить не обязательно.
После входа, вы сможете просматривать таблицы вашей БД без труда и в нормальном виде!
Комментарии (14)
 - klis17.04.2023 16:18+2- Я начинающий разработчик и хочу поделиться своим решением проблемы, с которой столкнулся и не нашел готового решения в интернете. - Серьезно? Это вот прям проблема, решение которой достойно аж отдельной статьи? И прям решений в интернете нет? 
 Попробуйте вот этот сайт https://letmegooglethat.com/?q=dockerize+django+postgres
 - Hivemaster17.04.2023 16:18+2- Шаг 1: Не суйте СУБД в контейнер. 
 Конец. - askolo4ek17.04.2023 16:18+1- Только что хотел это написать) Советую всегда БД на отдельном сервере разворачивать. Или в виртуалке, если учитесь и для себя делаете. Не нужно воплощать в жизнь плохие практики  - Bupyc17.04.2023 16:18- я так понимаю это касается прода, никогда не пихал базу в контейнер, но интересно почему это не рекомендуется? 
- сервис API тоже не рекомендуется в контейнере заливать на прод? 
  - askolo4ek17.04.2023 16:18+2- 
Дело в том, что контейнеры очень любят падать и штука эта вообще не стабильная. К примеру, вы поднимаете свой Django проект в контейнере вместе с БД, всё работает отлично. Трафик и идёт, пользователи авторизируются, базёнка всё сохраняет. Но вдруг происходит какая то ошибка и тогда сразу контейнер завершит свою работу и падает, и все данные в БД и сама БД исчезают. 
 Контейнеры нужны только для того, чтобы изолировать программу от хоста со своими зависимостями. Благодаря этому контейнеры жрут мало ресурсов по сравнению с ВМ. Но обратная сторона медали - это скудное его наполнение, только самое необходимое (файловая система, плюс возможность создать процесс). А держать БД в контейнере - плохая идея, потому что он в целом не предназначен под работу с дисковой памятью, да и изоляция БД от хостовой системы не требуется, потому что дисковая память итак изолирована, сегментирована. Если контейнер упадёт, то вы потеряте файл БД и все данные, там хранящиеся.
 Для решения проблемы устойчивости контейнеров как раз и придумали Kubernetes, который сам чуть что сбалансирует трафик, переподнимет, так же ещё можно сделать несколько реплик одного и того же приложения (для горизонтального масштабирования), можно задать количество потребляемых ресурсов на контейнер (RAM и CPU). Но Kubernetes также не решает проблемы БД (хотя потуги есть, например, StatefulSet)
- 
Сервис API в контейнере - это самое популярное и правильное решение. Но рекомендуется выносить БД на отдельный сервер, куда сервис API будет слать данные и брать оттуда. Так вы обеспечите сохранность и нивелируете кучу рисков. Также на сервере рекомендуется создать крон для бекапирования БД(на всякий случай). Ну и в идеале конечно вообще сделать несколько реплик БД, которые живут на разных серваках, географически разделенных с бекапами, блекджеком и тд :)). Так обеспечивается 99.99% сохранения данных. Также, желательно, на проде иметь Kubernetes, который и будет оркестрировать ваши контейнеры с сервисами. Для этого он представляет все возможности (внутреннюю сеть, неймспэйсы для изолирования, про реплики и балансировку описал выше) 
  - klis17.04.2023 16:18+2- Но вдруг происходит какая то ошибка и тогда сразу контейнер завершит свою работу и падает, и все данные в БД и сама БД исчезают. - Если контейнер упадёт, то вы потеряте файл БД и все данные, там хранящиеся. - Эм... Что, простите? - Но рекомендуется выносить БД на отдельный сервер - Кем рекомендуется? Поделитесь рефенсами на исследования об этом. Желательно за последние лет 10. 
 
- 
  - Hivemaster17.04.2023 16:18- На Stackoverflow есть хороший ответ на эту тему от одного из разработчиков PostgreSQL.  - klis17.04.2023 16:18-1- "PostgreSQL DBA, время от времени контрибьютор проекта." != разработчик PostgreSQL - Итак, файловая система необходима хоста, сеть необходима хоста. Итог - а зачем вам вообще база (в смысле получается только её исполняемые бинарники) в докере? Что вы отсюда хотите получить? - Я хочу отсюда получить возможность запускать в рамках одной машины десятки/сотни постгресов произвольных версий и, возможно, по разному настроенных. И потом так же просто их бесследно удалять. 
 
 
 
  - bekishev0417.04.2023 16:18- Для разработки почему бы и нет? 
 Когда у тебя много проектов, то очень удобно запустить бд для конкретно этого проекта одной командой, а потом так же быстро остановить- А в случае прода соглашусь 
 
 - kgenius17.04.2023 16:18+1- Стал замечать, что становится много токсичных комментариев к статьям хаба. Причем не негативных/отрицательнах, а именно токсичных. И не зависит причём от тематики. Печально конечно такую тенденцию наблюдать... :-(  - klis17.04.2023 16:18- Не переживайте, это, по всей видимости, продлится недолго - обнулить карму я, к сожалению, могу только один раз :) 
 По комментариям понятно. А наличие таких статей на хабре вас в целом воодушевляет или какие чувства вы испытываете? - kgenius17.04.2023 16:18- Хабр я читаю читаю постоянно. Конкретно данную статью смотрел обзорно (бегло), т.к. сам специализируюсь на других направлениях. 
 
 
 
           
 
rSedoy
добавлять django.contrib.postgres нужно только если используешь PostgreSQL specific features
настройки в DATABASES лучше передавать через переменные окружения, а не явно их прописывать. Для pgdb же сделано, почему так же и для остальных не сделать?
а зачем AutoField писать? он и так уже есть у Model
как использовать докер, хорошо посмотреть у крупных проектов на github, например, https://github.com/saleor/saleor-platform/blob/main/docker-compose.yml https://github.com/saleor/saleor/blob/main/Dockerfile