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


98

我已经按照Docker站点上的Django Quick Start指导紧密设置了Docker Django / PostgreSQL应用程序。

第一次运行Django的manage.py migration时,使用命令sudo docker-compose run web python manage.py migrate可以正常工作。该数据库建立在Docker PostgreSQL容器内就很好了。

当我保存它们时,对Django应用本身所做的更改同样会反映在Docker Django容器中。这很棒!

但是,如果我再改在Django的模型,并尝试更新的Postgres数据库来匹配模型,都没有检测到变化所以没有迁移发生,无论我有多少次运行makemigrationsmigrate试。

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

我仍在努力了解Docker,但我对它的工作方式有很多不了解,但这使我发疯。为什么不迁移看到我的更改?我究竟做错了什么?


你知道为什么吗?我在下面得到了答案,并且可以正常工作:You just have to log into your running docker container and run your commands.但是,这样做的原因是什么?@LouisBarranqueiro
lukik

Answers:


102

您只需登录到正在运行的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自动运行:

  • 碰撞的
  • 迁移
  • 运行服务器或使用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

16
我还建议您为django docker容器文件使用docker-entrypoint自动运行 -此类操作永远不应自动运行- 特别是迁移
蛋白石

7
无论您在哪个环境上都可以-部署应该始终看起来相同。如果迁移是自动化的,则强烈建议不要同时进行迁移。例如在heroku上-迁移永远不会作为部署的一部分运行。
蛋白石

5
一致地?在这里,我们处于开发环境中。我跑makemigrations。下次启动堆栈时,migrate将使用上一次迁移来更新数据库,否则django应用程序将无法正常运行...这只是开发环境中的快捷方式,可确保您使用当前应用程序获得正确的数据库架构
Louis Barranqueiro 2015年

2
@LouisBarranqueiro,我的意思是多个实例,单个数据库。
蛋白石

1
对于步骤4,我建议:docker exec -ti $ CONTAINER_ID / bin / sh
SantiagoMagariños19年

52

我使用这些方法:

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服务器相同的映像,则意味着所有迁移都将从项目中进行,从而避免了问题。

这样可以避免进入入口或其他任何事情。


1
我如何build: .处理image: 错误消息,即迁移无法提取命名的映像
Aaron McMillin

2
我通过继续使用来解决了该问题build:migration因为它会在之前运行web
Aaron McMillin

4
这不是让uzman映像永久运行并消耗RAM吗?此外,什么该uzman形象?
mlissner '19

这是我自定义的docker镜像,我还没有测试RAM。
SalahAdD19年

32

让您的堆栈运行,然后触发一键式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/


12

您可以使用docker exec命令

docker exec -it container_id python manage.py migrate

1
这应该是答案。
tolga

要获取提到的container_id,请执行docker ps然后查找django服务器的COMMAND列。
Jai Sharma

5

如果你有这样的事情 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

2

我知道这很旧了,也许我在这里丢失了一些东西(如果是的话,请告诉我!),但是为什么不只是将命令添加到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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.