Como você executa migrações de banco de dados Django ao usar Docker-Compose?

98

Eu configurei um aplicativo Docker Django / PostgreSQL seguindo de perto as instruções do Django Quick Start no site Docker .

A primeira vez que executo o manage.py migrate do Django, usando o comando sudo docker-compose run web python manage.py migrate, ele funciona conforme o esperado. O banco de dados é construído dentro do contêiner Docker PostgreSQL perfeitamente.

As alterações feitas no próprio aplicativo Django são refletidas da mesma forma no contêiner Docker Django, no momento em que eu as salvo. É ótimo!

Mas se eu mudar um modelo no Django e tentar atualizar o banco de dados Postgres para corresponder ao modelo, nenhuma mudança é detectada, então nenhuma migração acontece, não importa quantas vezes eu execute makemigrationsou migratenovamente.

Basicamente, toda vez que eu mudo o modelo Django, tenho que deletar os contêineres do Docker (usando sudo docker-compose rm) e começar do zero com uma nova migração.

Ainda estou tentando entender o Docker e há muita coisa que não entendo sobre como funciona, mas esse está me deixando maluco. Por que a migração não vê minhas alterações? O que estou fazendo de errado?

John
fonte
Você descobriu por quê? Recebo a resposta abaixo e funciona: You just have to log into your running docker container and run your commands.mas qual é a razão de ele se comportar dessa forma? @LouisBarranqueiro
lukik

Respostas:

102

Você só precisa fazer login no contêiner do docker em execução e executar seus comandos.

  1. Construa sua pilha: docker-compose build -f path/to/docker-compose.yml
  2. Lance sua pilha: docker-compose up -f path/to/docker-compose.yml
  3. Exibir contêineres em execução do 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. Obtenha o CONTAINER ID do seu aplicativo Django e faça login em:
docker exec -t -i 66175bfd6ae6 bash
  1. Agora que você está conectado, vá para a pasta certa: cd path/to/django_app

  2. E agora, cada vez que você editar seus modelos, execute em seu contêiner: python manage.py makemigrationsepython manage.py migrate

Também recomendo que você use um docker-entrypoint para que o arquivo django docker contêiner seja executado automaticamente:

  • colecstático
  • migrar
  • runserver ou inicie-o com gunicorn ou uWSGI

Aqui está um exemplo ( 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
Louis Barranqueiro
fonte
16
Eu também recomendo que você use um docker-entrypoint para que seu arquivo django docker contêiner seja executado automaticamente - tais operações nunca devem ser executadas automaticamente - quero dizer migrar especialmente.
Opala
7
Não importa em qual ambiente você está - a implantação deve ser sempre a mesma. Se as migrações forem automatizadas, elas podem ser executadas simultaneamente, o que é altamente desencorajado. Por exemplo, no heroku - as migrações nunca são executadas como parte do deploy.
Opala
5
concomitantemente? Aqui estamos em um env dev. Eu corro makemigrations. na próxima vez que eu lançar minha pilha, migrateatualizarei o banco de dados com as últimas migrações desfeitas, caso contrário, o aplicativo django não funcionará corretamente ... É apenas um atalho no env dev para ter certeza de que obteve o esquema de banco de dados correto com o aplicativo atual
Louis Barranqueiro
2
@LouisBarranqueiro, quis dizer várias instâncias, um único banco de dados.
Opala
1
Para a etapa 4, eu recomendaria: docker exec -ti $ CONTAINER_ID / bin / sh
Santiago Magariños,
52

Eu uso estes métodos:

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

Usando a dockerhierarquia que fizemos, a migração do serviço é executada após a configuração do banco de dados e antes de executar o serviço principal. Agora, quando você executar o serviço, dockerfará migrações antes de executar o servidor; olhe que migrationservidor é aplicado sobre a mesma imagem que servidor web, isso significa que todas as migrações serão tiradas do seu projeto, evitando problemas.

Você evita um ponto de entrada feito ou qualquer outra coisa com este caminho.

SalahAdDin
fonte
1
Como build: .funciona? image: Obtenho o erro de que a migração não pode puxar a imagem nomeada
Aaron McMillin
2
Resolvi-lo, colocando o build:em migrationuma vez que será executado antesweb
Aaron McMillin
4
Isso não mantém a imagem do uzman funcionando e consumindo RAM para sempre? Além disso, qual é a imagem do uzman?
mlissner de
É minha imagem docker personalizada. Ainda não testei a RAM.
SalahAdDin de
32

Coloque sua pilha em execução e dispare um comando docker-compose run de um tiro. Por exemplo

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

Isso funciona muito bem para o banco de dados SQLite interno (padrão), mas também para um banco de dados dockerizado externo listado como dependência. Aqui está um exemplo de arquivo 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/

Oliver Shaw
fonte
12

Você pode usar o docker execcomando

docker exec -it container_id python manage.py migrate
Super Nova
fonte
1
Esta deve ser a resposta.
Tolga
Para obter o container_id mencionado, faça docker pse então procure a coluna COMMAND para o servidor Django.
Jai Sharma
5

Se você tem algo assim em seu 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

Então você pode simplesmente executar ...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate
Robert Johnstone
fonte
2

Eu sei que isso é antigo, e talvez esteja faltando alguma coisa aqui (em caso afirmativo, por favor me esclareça!), Mas por que não apenas adicionar os comandos ao seu start.shscript, executado pelo Docker para iniciar sua instância? Isso levará apenas alguns segundos extras.

NB eu defini oDJANGO_SETTINGS_MODULE variável para garantir que o banco de dados correto seja usado, já que uso diferentes bancos de dados para desenvolvimento e produção (embora eu saiba que isso não é 'melhor prática').

Isso resolveu para mim:

#!/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
TBZ92
fonte
1

Usando o docker exec, estava recebendo o seguinte erro:

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

Então, usei este comando:

docker-compose -f local.yml run django python manage.py makemigrations
Santiago Magariños
fonte