Bagaimana Anda melakukan migrasi basis data Django saat menggunakan Docker-Compose?

110

Saya telah menyiapkan aplikasi Docker Django / PostgreSQL dengan cermat mengikuti petunjuk Mulai Cepat Django di situs Docker .

Pertama kali saya menjalankan manage.py migrate Django, menggunakan perintah sudo docker-compose run web python manage.py migrate, ini bekerja seperti yang diharapkan. Basis data dibangun di dalam wadah Docker PostgreSQL dengan baik.

Perubahan yang dibuat pada aplikasi Django itu sendiri juga tercermin dalam wadah Docker Django, saat saya menyimpannya. Itu bagus!

Tetapi jika saya kemudian mengubah model di Django, dan mencoba memperbarui database Postgres agar cocok dengan model, tidak ada perubahan yang terdeteksi sehingga tidak ada migrasi yang terjadi tidak peduli berapa kali saya menjalankan makemigrationsatau migratelagi.

Pada dasarnya, setiap kali saya mengubah model Django, saya harus menghapus wadah Docker (menggunakan sudo docker-compose rm) dan memulai lagi dengan migrasi baru.

Saya masih mencoba untuk memahami Docker, dan ada banyak hal yang tidak saya mengerti tentang cara kerjanya, tetapi yang ini membuat saya gila. Mengapa migrasi tidak melihat perubahan saya? Apa yang saya lakukan salah?

John
sumber
Apakah kamu sudah tahu kenapa? Saya mendapatkan jawabannya di bawah ini dan berhasil: You just have to log into your running docker container and run your commands.tetapi apa alasannya berperilaku seperti itu? @LouisBarranqueiro
lukik

Jawaban:

115

Anda hanya perlu masuk ke kontainer buruh pelabuhan yang sedang berjalan dan menjalankan perintah Anda.

  1. Bangun tumpukan Anda: docker-compose build -f path/to/docker-compose.yml
  2. Luncurkan tumpukan Anda: docker-compose up -f path/to/docker-compose.yml
  3. Tampilkan kontainer yang menjalankan buruh pelabuhan: 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. Dapatkan ID PENAMPUNG dari aplikasi django Anda dan login ke:
docker exec -t -i 66175bfd6ae6 bash
  1. Sekarang Anda masuk, lalu pergi ke folder kanan: cd path/to/django_app

  2. Dan sekarang, setiap kali Anda mengedit model Anda, jalankan di penampung Anda: python manage.py makemigrationsdanpython manage.py migrate

Saya juga merekomendasikan Anda untuk menggunakan titik entri buruh pelabuhan agar file kontainer buruh pelabuhan django Anda berjalan secara otomatis:

  • collecstatic
  • migrasi
  • runserver atau mulai dengan gunicorn atau uWSGI

Berikut adalah contoh ( 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
sumber
16
Saya juga merekomendasikan Anda untuk menggunakan titik entri buruh pelabuhan untuk file kontainer buruh pelabuhan django Anda untuk berjalan secara otomatis - operasi semacam itu tidak boleh dijalankan secara otomatis - maksud saya terutama bermigrasi .
Opal
7
Tidak masalah di lingkungan mana Anda - penerapan harus selalu terlihat sama. Jika migrasi diotomatiskan, mungkin berjalan secara bersamaan yang sangat tidak disarankan. Misalnya tentang heroku - migrasi tidak pernah dijalankan sebagai bagian dari penerapan.
Opal
5
secara bersamaan? Di sini kita berada di dev env. Saya menjalankan makemigrations. lain kali saya meluncurkan tumpukan saya, migrateakan memperbarui basis data dengan migrasi terakhir dibatalkan, jika tidak aplikasi django tidak akan berfungsi dengan benar ... Ini hanya pintasan di dev env untuk memastikan Anda mendapatkan skema basis data yang benar dengan aplikasi saat ini
Louis Barranqueiro
2
@LouisBarranqueiro, maksud saya banyak contoh, DB tunggal.
Opal
1
Untuk langkah 4, saya akan merekomendasikan: buruh pelabuhan exec -ti $ CONTAINER_ID / bin / sh
Santiago Magariños
51

Saya menggunakan metode ini:

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

Menggunakan dockerhierarki yang kami buat, migrasi layanan berjalan setelah menyiapkan database dan sebelum menjalankan layanan utama. Sekarang ketika Anda menjalankan layanan Anda dockerakan menjalankan migrasi sebelum menjalankan server; lihat bahwa migrationserver diterapkan pada gambar yang sama dengan server web, itu berarti bahwa semua migrasi akan diambil dari proyek Anda, menghindari masalah.

Anda menghindari dibuat titik masuk atau hal lain dengan cara ini.

SalahAdDin
sumber
2
Bagaimana cara build: .bekerja dengan image: saya mendapatkan kesalahan bahwa migrasi tidak dapat menarik gambar bernama
Aaron McMillin
2
Saya diselesaikan dengan menempatkan build:pada migrationkarena akan dijalankan sebelumweb
Aaron McMillin
5
Bukankah ini membuat image uzman tetap berjalan dan memakan RAM selamanya? Juga, apa yang gambar Uzman?
mlissner
Ini adalah gambar buruh pelabuhan khusus saya, saya belum menguji RAM-nya.
SalahAdDin
33

Buat tumpukan Anda berjalan kemudian jalankan perintah jalankan pembuat galangan satu tembakan. Misalnya

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

Ini berfungsi dengan baik untuk database SQLite bawaan (default), tetapi juga untuk database eksternal docker yang terdaftar sebagai dependensi. Berikut ini contoh file 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
sumber
12

Anda dapat menggunakan docker execperintah

docker exec -it container_id python manage.py migrate
SuperNova
sumber
1
Ini harus menjadi jawabannya.
tolga
Untuk mendapatkan container_id disebutkan, lakukan docker psdan kemudian cari kolom COMMAND untuk server django.
Jai Sharma
6

Jika Anda memiliki sesuatu seperti ini di file 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

Kemudian Anda dapat menjalankan ...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate
Robert Johnstone
sumber
3

Saya tahu ini sudah lama, dan mungkin saya kehilangan sesuatu di sini (jika demikian, tolong beri tahu saya!), Tetapi mengapa tidak menambahkan perintah ke start.shskrip Anda , dijalankan oleh Docker untuk menjalankan instance Anda? Ini hanya membutuhkan beberapa detik ekstra.

NB Saya menetapkan DJANGO_SETTINGS_MODULEvariabel untuk memastikan database yang benar digunakan, karena saya menggunakan database yang berbeda untuk pengembangan dan produksi (meskipun saya tahu ini bukan 'praktik terbaik').

Ini menyelesaikannya untuk saya:

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

Menggunakan buruh pelabuhan exec, saya mendapatkan kesalahan berikut:

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

Jadi saya menggunakan perintah ini sebagai gantinya:

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