簡體   English   中英

使用 Docker-Compose 時如何執行 Django 數據庫遷移?

[英]How do you perform Django database migrations when using Docker-Compose?

我已經按照 Docker 站點上的 Django 快速入門說明設置了一個 Docker Django/PostgreSQL 應用程序。

我第一次運行 Django 的 manage.py migrate 時,使用命令sudo docker-compose run web python manage.py migrate ,它按預期工作。 數據庫構建在 Docker PostgreSQL 容器中就好了。

在我保存它們的那一刻,對 Django 應用程序本身所做的更改同樣反映在 Docker Django 容器中。 這很棒!

但是,如果我隨后在 Django 中更改模型,並嘗試更新 Postgres 數據庫以匹配該模型,則不會檢測到任何更改,因此無論我運行makemigrations或再次migrate多少次都不會發生migrate

基本上,每次更改 Django 模型時,我都必須刪除 Docker 容器(使用sudo docker-compose rm )並重新開始新的遷移。

我仍在努力了解 Docker,我不明白它是如何工作的,但這個讓我發瘋。 為什么遷移看不到我的更改? 我究竟做錯了什么?

您只需要登錄正在運行的 docker 容器並運行您的命令。

  1. 構建你的堆棧: docker-compose build -f path/to/docker-compose.yml
  2. 啟動您的堆棧: docker-compose up -f path/to/docker-compose.yml
  3. 顯示 docker 正在運行的容器: docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
3fcc49196a84        ex_nginx          "nginx -g 'daemon off"   3 days ago          Up 32 seconds       0.0.0.0:80->80/tcp, 443/tcp   ex_nginx_1
66175bfd6ae6        ex_webapp         "/docker-entrypoint.s"   3 days ago          Up 32 seconds       0.0.0.0:32768->8000/tcp       ex_webapp_1
# postgres docker container ...
  1. 獲取 django 應用程序的容器 ID並登錄:
docker exec -t -i 66175bfd6ae6 bash
  1. 現在您已登錄,然后轉到正確的文件夾: cd path/to/django_app

  2. 現在,每次編輯模型時,請在容器中運行: python manage.py makemigrationspython manage.py migrate

我還建議您為 django docker 容器文件使用 docker-entrypoint 以自動運行:

  • 收藏的
  • 遷移
  • runserver或使用 gunicorn 或 uWSGI 啟動它

這是一個示例( docker-entrypoint.sh ):

#!/bin/bash

# Collect static files
echo "Collect static files"
python manage.py collectstatic --noinput

# Apply database migrations
echo "Apply database migrations"
python manage.py migrate

# Start server
echo "Starting server"
python manage.py runserver 0.0.0.0:8000

我使用這些方法:

services:
  web:
    build: .
    image: uzman
    command: python manage.py runserver 0.0.0.0:8000
    ports:
      - "3000:3000"
      - "8000:8000"
    volumes:
      - .:/code
    depends_on:
      - migration
      - db
  migration:
    image: uzman
    command: python manage.py migrate --noinput
    volumes:
      - .:/code
    depends_on:
      - db

使用我們創建的docker層次結構,服務遷移在設置數據庫之后運行,並在運行主服務之前運行。 現在,當您運行服務時, docker將在運行服務器之前運行遷移; 看看migration服務器應用在與 Web 服務器相同的圖像上,這意味着所有遷移都將從您的項目中獲取,從而避免出現問題。

通過這種方式,您可以避免制作入口點或其他任何東西。

讓你的堆棧運行,然后發出一個一次性的 docker-compose run 命令。 例如

#assume django in container named web
docker-compose run web python3 manage.py migrate

這適用於內置(默認)SQLite 數據庫,但也適用於列為依賴項的外部 dockerized 數據庫。 這是一個示例 docker-compose.yaml 文件

version: '3'

services:
  db:
    image: postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

https://docs.docker.com/compose/reference/run/

您可以使用docker exec命令

docker exec -it container_id python manage.py migrate

如果你docker-compose.yml有這樣的東西

version: "3.7"

services:

  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
    - 8000:8000
    volumes:
        - ./:/usr/src/app
    depends_on:
      - db

  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: docker
      POSTGRES_PASSWORD: docker
      POSTGRES_DB: docker

然后你可以簡單地運行...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate

您可以使用docker-entrypoint.sh或者更新的解決方案將是您docker-compose.yml多個注釋

version: '3.7'

services:
  web:
    build: ./
    command: >
      sh -c "python manage.py collectstatic --noinput &&
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000"
    volumes:
      - ./:/usr/src/app/
    ports:
      - 8000:8000
    env_file:
      - ./.env
    depends_on:
      - postgres

  postgres:
    image: postgres:13.0-alpine
    ports:
      - 5432:5432
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres

我知道這是舊的,也許我在這里遺漏了一些東西(如果是這樣,請賜教!),但是為什么不將命令添加到您的start.sh腳本中,由 Docker 運行以啟動您的實例? 它只需要額外的幾秒鍾。

注意,我設置了DJANGO_SETTINGS_MODULE變量以確保使用正確的數據庫,因為我使用不同的數據庫進行開發和生產(盡管我知道這不是“最佳實踐”)。

這為我解決了:

#!/bin/bash
# Migrate the database first
echo "Migrating the database before starting the server"
export DJANGO_SETTINGS_MODULE="edatool.settings.production"
python manage.py makemigrations
python manage.py migrate
# Start Gunicorn processes
echo "Starting Gunicorn."
exec gunicorn edatool.wsgi:application \
    --bind 0.0.0.0:8000 \
    --workers 3

使用 docker exec,我收到以下錯誤:

AppRegistryNotReady("Models aren't loaded yet.")

所以我改用這個命令:

docker-compose -f local.yml run django python manage.py makemigrations

如果只想使用 Dockerfile,可以添加 ENTRYPOINT[] 命令。 示例如何運行 .sh 腳本:

FROM python:3.9.4
RUN apt-get update
RUN apt-get install libpq-dev --assume-yes
RUN pip3 install psycopg2

COPY . /app
WORKDIR /app

RUN pip install -r requirements.txt
RUN pip3 install debugpy

ENTRYPOINT ["/app/docker-entrypoint.sh"]

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM