คุณดำเนินการย้ายฐานข้อมูล Django อย่างไรเมื่อใช้ Docker-Compose


110

ฉันได้ตั้งค่าแอปหาง Django / PostgreSQL อย่างใกล้ชิดต่อไปนี้คำแนะนำ Django Quick Start บนเว็บไซต์เทียบท่า

ครั้งแรกที่ฉันเรียกใช้ Manage.py migrate ของ Django โดยใช้คำสั่งsudo docker-compose run web python manage.py migrateมันทำงานได้ตามที่คาดไว้ ฐานข้อมูลถูกสร้างขึ้นภายในคอนเทนเนอร์ Docker PostgreSQL ได้ดี

การเปลี่ยนแปลงที่เกิดขึ้นกับแอป Django เองก็สะท้อนให้เห็นในคอนเทนเนอร์ Docker Django เช่นเดียวกันในขณะที่ฉันบันทึก มันยอดมาก!

แต่ถ้าฉันเปลี่ยนโมเดลใน Django และพยายามอัปเดตฐานข้อมูล Postgres ให้ตรงกับโมเดลจะไม่มีการตรวจพบการเปลี่ยนแปลงดังนั้นจึงไม่มีการย้ายข้อมูลไม่ว่าฉันจะเรียกใช้กี่ครั้งmakemigrationsหรือmigrateอีกครั้ง

โดยทั่วไปทุกครั้งที่ฉันเปลี่ยนโมเดล Django ฉันต้องลบคอนเทนเนอร์ Docker (โดยใช้sudo docker-compose rm) และเริ่มต้นใหม่ด้วยการย้ายข้อมูลใหม่

ฉันยังคงพยายามเอาหัวของฉันไปรอบ ๆ Docker และมีหลายอย่างที่แย่มากที่ฉันไม่เข้าใจเกี่ยวกับวิธีการทำงาน แต่สิ่งนี้ทำให้ฉันรู้สึกแย่ ทำไมย้ายข้อมูลไม่เห็นการเปลี่ยนแปลงของฉัน ผมทำอะไรผิดหรือเปล่า?


คุณคิดออกว่าทำไม? ฉันได้รับคำตอบด้านล่างและได้ผล: You just have to log into your running docker container and run your commands.แต่อะไรคือสาเหตุที่ทำให้มันทำงานแบบนั้น? @LouisBarranqueiro
lukik

คำตอบ:


115

คุณต้องลงชื่อเข้าใช้คอนเทนเนอร์นักเทียบท่าที่กำลังทำงานอยู่และเรียกใช้คำสั่งของคุณ

  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. รับID คอนเทนเนอร์ของแอพ django ของคุณและเข้าสู่ระบบ:
docker exec -t -i 66175bfd6ae6 bash
  1. ตอนนี้คุณเข้าสู่ระบบแล้วไปที่โฟลเดอร์ที่ถูกต้อง: cd path/to/django_app

  2. และตอนนี้ทุกครั้งที่คุณแก้ไขโมเดลของคุณให้เรียกใช้ในคอนเทนเนอร์ของคุณ: python manage.py makemigrationsและpython manage.py migrate

ฉันขอแนะนำให้คุณใช้ Docker-entrypoint เพื่อให้ไฟล์คอนเทนเนอร์ django docker ของคุณทำงานโดยอัตโนมัติ:

  • วิทยาลัย
  • โยกย้าย
  • runerverหรือเริ่มต้นด้วย 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
ฉันขอแนะนำให้คุณใช้ docker-entrypoint เพื่อให้ไฟล์คอนเทนเนอร์ django docker ของคุณทำงานโดยอัตโนมัติ - การดำเนินการดังกล่าวไม่ควรทำงานโดยอัตโนมัติ - ฉันหมายถึงการโยกย้ายโดยเฉพาะ
Opal

7
ไม่สำคัญว่าคุณจะอยู่ในสภาพแวดล้อมใด - การปรับใช้ควรมีลักษณะเหมือนกันเสมอ หากการย้ายข้อมูลเป็นไปโดยอัตโนมัติอาจมีการรันพร้อมกันซึ่งไม่แนะนำอย่างยิ่ง เช่นบน heroku - การย้ายข้อมูลจะไม่ถูกเรียกใช้เป็นส่วนหนึ่งของการปรับใช้
Opal

5
อย่างรวบรัด? ที่นี่เราอยู่ในสภาพแวดล้อมการพัฒนา makemigrationsฉันวิ่ง ในครั้งต่อไปที่ฉันเปิดสแต็กmigrateจะอัปเดตฐานข้อมูลโดยยกเลิกการย้ายข้อมูลครั้งสุดท้ายมิฉะนั้นแอป django จะทำงานไม่ถูกต้อง ... เป็นเพียงทางลัดใน dev env เพื่อให้แน่ใจว่าคุณมีสคีมาฐานข้อมูลที่ถูกต้องกับแอปปัจจุบัน
Louis Barranqueiro

2
@LouisBarranqueiro ฉันหมายถึงหลายอินสแตนซ์ DB เดียว
Opal

1
สำหรับขั้นตอนที่ 4 ฉันขอแนะนำ: นักเทียบท่า exec -ti $ CONTAINER_ID / bin / sh
Santiago Magariños

51

ฉันใช้วิธีการเหล่านี้:

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เซิร์ฟเวอร์ถูกนำไปใช้กับรูปภาพเดียวกันกับเว็บเซิร์ฟเวอร์นั่นหมายความว่าการย้ายข้อมูลทั้งหมดจะถูกนำมาจากโปรเจ็กต์ของคุณเพื่อหลีกเลี่ยงปัญหา

คุณหลีกเลี่ยงจุดเข้าหรือสิ่งอื่นใดด้วยวิธีนี้


2
วิธีการbuild: .ทำงานร่วมกับimage: ฉันได้รับข้อผิดพลาดที่ย้ายถิ่นไม่สามารถดึงภาพชื่อ
แอรอน McMillin

2
ฉันแก้ไขมันโดยการวางbuild:ไว้migrationเนื่องจากมันจะทำงานก่อนweb
Aaron McMillin

5
สิ่งนี้ไม่ทำให้อิมเมจ uzman ทำงานและใช้ RAM ตลอดไปหรือไม่? นอกจากนี้สิ่งที่เป็นภาพ Uzman หรือไม่
mlissner

มันเป็นอิมเมจนักเทียบท่าที่กำหนดเองของฉันฉันยังไม่ได้ทดสอบแรม
SalahAdDin

33

ให้สแต็กของคุณทำงานจากนั้นยิงคำสั่ง 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แล้วมองหาคอลัมน์ COMMAND สำหรับเซิร์ฟเวอร์ django
Jai Sharma

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

3

ฉันรู้ว่านี่เก่าแล้วและบางทีฉันอาจจะพลาดอะไรบางอย่างที่นี่ (ถ้าเป็นเช่นนั้นโปรดสอนฉันด้วย!) แต่ทำไมไม่เพียงแค่เพิ่มคำสั่งลงใน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

1

เมื่อใช้ docker exec ฉันได้รับข้อผิดพลาดต่อไปนี้:

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

ดังนั้นฉันจึงใช้คำสั่งนี้แทน:

docker-compose -f local.yml run django python manage.py makemigrations
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.