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

时间:2015-11-30 06:45:36

标签: django docker docker-compose

我已经在Django Quick Start instructions on the Docker site之后设置了一个Docker Django / PostgreSQL应用程序。

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

对Django应用程序本身所做的更改同样反映在Docker Django容器中,我保存它们的那一刻。太棒了!

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

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

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

9 个答案:

答案 0 :(得分:59)

您只需登录正在运行的docker容器并运行命令。

  1. 构建堆栈:docker-compose build -f path/to/docker-compose.yml
  2. 启动您的筹码:docker-compose up -f path/to/docker-compose.yml
  3. 显示运行容器的泊坞窗:docker ps
  4. 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 app的 CONTAINER ID 并登录:
    2. docker exec -t -i 66175bfd6ae6 bash
      
      1. 现在您已登录,然后转到右侧文件夹:cd path/to/django_app

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

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

        • collecstatic
        • 迁移
        • 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
        

答案 1 :(得分:34)

我使用这些方法:

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服务器相同的映像,这意味着将从您的项目中获取所有迁移,避免出现问题。

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

答案 2 :(得分:15)

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

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

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

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

答案 3 :(得分:6)

如果您的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

答案 4 :(得分:2)

您可以使用 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

答案 5 :(得分:1)

您可以使用docker exec命令

docker exec -it container_id python manage.py migrate

答案 6 :(得分:0)

我知道这很旧了,也许我在这里丢失了一些东西(如果是,请给我启发!),但是为什么不将命令添加到由Docker运行的start.sh脚本中以启动您的实例?仅需几秒钟的时间。

NB 我设置了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

答案 7 :(得分:0)

使用docker exec,出现以下错误:

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

所以我改用以下命令:

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

答案 8 :(得分:0)

如果你只想使用 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"]