使用Docker-Compose时如何执行Django数据库迁移?

Joh*_*ohn 72 django docker docker-compose

我已经按照Docker站点上的Django Quick Start说明严格设置了Docker Django/PostgreSQL应用程序.

我第一次运行Django的manage.py migrate,使用该命令sudo docker-compose run web python manage.py migrate,它按预期工作.数据库是在Docker PostgreSQL容器内构建的.

Django应用程序本身的更改同样反映在Docker Django容器中,我保存它们的那一刻.这很棒!

但是如果我然后在Django中更改模型,并尝试更新Postgres数据库以匹配模型,则不会检测到任何更改,因此无论我运行多少次makemigrationsmigrate再次运行都不会发生迁移.

基本上,每次我更改Django模型时,我都必须删除Docker容器(使用sudo docker-compose rm)并重新启动新的迁移.

我仍然试图让我的头围绕Docker,并且有很多我不明白它是如何工作的,但是这个让我疯狂.为什么不迁移看到我的更改?我究竟做错了什么?

Lou*_*iro 70

您只需登录正在运行的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 ...
Run Code Online (Sandbox Code Playgroud)
  1. 获取您的django app 的CONTAINER ID并登录:
docker exec -t -i 66175bfd6ae6 bash
Run Code Online (Sandbox Code Playgroud)
  1. 现在您已登录,然后转到右侧文件夹: cd path/to/django_app

  2. 现在,每次编辑模型时,都要在容器中运行:python manage.py makemigrationspython manage.py migrate

我还建议您使用docker-entrypoint为您的django docker容器文件自动运行:

  • collecstatic
  • 迁移
  • 运行服务器或用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
Run Code Online (Sandbox Code Playgroud)

  • *我还建议您使用docker-entrypoint为您的django docker容器文件自动运行* - 此类操作永远不应自动运行 - 我的意思是*migrate*尤其如此. (11认同)
  • 在哪个环境中无关紧要 - 部署应始终保持一致.如果迁移是自动化的,那么可能会同时运行,这是非常不鼓励的.例如,在heroku上 - 迁移永远不会作为部署的一部分运行. (6认同)
  • 这是为什么?我们处于开发环境中。 (3认同)
  • concurently?在这里,我们在开发环境中.我运行`makemigrations`.下次我启动堆栈时,`migrate`会在上次迁移时更新数据库,否则django app将无法正常运行...它只是dev env中的一个快捷方式,可确保您获得正确的数据库架构当前的应用 (3认同)
  • @LouisBarranqueiro,我的意思是多个实例,单个数据库。 (3认同)

Sal*_*Din 41

我用这些方法:

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
Run Code Online (Sandbox Code Playgroud)

使用docker我们制作的层次结构,服务迁移在设置数据库之后和运行主服务之前运行.现在,当您运行服务时,docker将在运行服务器之前运行迁移; 看看migration服务器应用于与Web服务器相同的映像,这意味着所有迁移都将从您的项目中获取,从而避免出现问题.

你可以通过这种方式避免使用入口点或其他任何东西.

  • 这不会让 uzman 映像永远运行并消耗 RAM 吗?另外,乌兹曼形象*是什么*? (7认同)
  • depends_on 仅保证迁移服务在 Web 服务启动之前启动,但不能确保迁移服务在 Web 服务启动之前已完成正在运行的迁移。如果数据库需要更长的时间来启动或迁移需要更多的时间,这种方法仍然可能面临问题。 (4认同)
  • `build: .` 如何与 `image: ` 一起使用,我收到迁移无法拉取命名图像的错误 (3认同)
  • 我通过将 `build:` 放在 `migration` 上解决了这个问题,因为它将在 `web` 之前运行 (3认同)

小智 32

您可以使用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
Run Code Online (Sandbox Code Playgroud)


Oli*_*haw 24

线程有点旧.但到目前为止还没有列出另一种方法.

让你的堆栈运行,然后启动一次性docker-compose运行命令.例如

#assume django in container named web
docker-compose run web python3 manage.py migrate
Run Code Online (Sandbox Code Playgroud)

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


Sup*_*ova 16

您可以使用docker exec命令

docker exec -it container_id python manage.py migrate
Run Code Online (Sandbox Code Playgroud)

  • 要获取提到的container_id,请执行“docker ps”,然后查找 django 服务器的 COMMAND 列。 (2认同)

Sev*_*ths 7

如果你有这样的东西 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
Run Code Online (Sandbox Code Playgroud)

然后你可以简单地运行...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate
Run Code Online (Sandbox Code Playgroud)

  • 非常肯定应该在开发期间使用 makemigrations。当您推进构建时,只需要迁移即可。 (4认同)

San*_*ños 6

使用 docker exec,我收到以下错误:

AppRegistryNotReady("Models aren't loaded yet.")
Run Code Online (Sandbox Code Playgroud)

所以我改用这个命令:

docker-compose -f local.yml run django python manage.py makemigrations
Run Code Online (Sandbox Code Playgroud)