Làm cách nào để bạn thực hiện di chuyển cơ sở dữ liệu Django khi sử dụng Docker-Compose?


99

Tôi đã thiết lập ứng dụng Docker Django / PostgreSQL theo đúng hướng dẫn Bắt đầu nhanh Django trên trang web Docker .

Lần đầu tiên tôi chạy di chuyển management.py của Django bằng cách sử dụng lệnh sudo docker-compose run web python manage.py migrate, nó hoạt động như mong đợi. Cơ sở dữ liệu được xây dựng bên trong vùng chứa Docker PostgreSQL tốt.

Các thay đổi được thực hiện đối với bản thân ứng dụng Django cũng được phản ánh trong vùng chứa Docker Django, tại thời điểm tôi lưu chúng. Thật tuyệt vời!

Nhưng nếu tôi sau đó thay đổi một mô hình trong Django, và cố gắng cập nhật cơ sở dữ liệu Postgres để phù hợp với mô hình, không có thay đổi được phát hiện vì vậy không di cư xảy ra dù có bao nhiêu lần tôi chạy makemigrationshoặc migratemột lần nữa.

Về cơ bản, mỗi khi tôi thay đổi mô hình Django, tôi phải xóa các vùng chứa Docker (đang sử dụng sudo docker-compose rm) và bắt đầu lại với một lần di chuyển mới.

Tôi vẫn đang cố gắng tìm hiểu Docker, và có rất nhiều điều tôi không hiểu về cách hoạt động của nó, nhưng điều này khiến tôi phát điên. Tại sao di chuyển không thấy các thay đổi của tôi? Tôi đang làm gì sai?


Bạn đã hiểu tại sao chưa? Tôi nhận được câu trả lời bên dưới và nó hoạt động: You just have to log into your running docker container and run your commands.nhưng lý do gì khiến nó hoạt động như vậy? @LouisBarranqueiro
lukik

Câu trả lời:


104

Bạn chỉ cần đăng nhập vào vùng chứa docker đang chạy của mình và chạy các lệnh của mình.

  1. Xây dựng ngăn xếp của bạn: docker-compose build -f path/to/docker-compose.yml
  2. Khởi chạy ngăn xếp của bạn: docker-compose up -f path/to/docker-compose.yml
  3. Hiển thị các bộ chứa đang chạy 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. Lấy ID CONTAINER của ứng dụng django của bạn và đăng nhập vào:
docker exec -t -i 66175bfd6ae6 bash
  1. Bây giờ bạn đã đăng nhập, sau đó chuyển đến thư mục bên phải: cd path/to/django_app

  2. Và bây giờ, mỗi khi bạn chỉnh sửa mô hình của mình, hãy chạy trong vùng chứa của bạn: python manage.py makemigrationspython manage.py migrate

Tôi cũng khuyên bạn nên sử dụng một docker-entrypoint để tệp vùng chứa docker django của bạn chạy tự động:

  • tập thể
  • di cư
  • runningerver hoặc khởi động nó bằng gunicorn hoặc uWSGI

Đây là một ví dụ ( 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
Tôi cũng khuyên bạn nên sử dụng một docker-entrypoint để tệp vùng chứa django docker của bạn chạy tự động - các hoạt động như vậy không bao giờ được chạy tự động - ý tôi là đặc biệt nên di chuyển .
Opal,

7
Không quan trọng bạn đang ở môi trường nào - việc triển khai phải luôn giống nhau. Nếu quá trình di chuyển được tự động, nó có thể được chạy đồng thời, điều này rất không được khuyến khích. Ví dụ: trên heroku - việc di chuyển không bao giờ được chạy như một phần của triển khai.
Opal,

5
một cách ngắn gọn? Ở đây chúng ta đang ở trong một env dev. Tôi chạy makemigrations. lần sau khi tôi khởi chạy ngăn xếp của mình, migratesẽ cập nhật cơ sở dữ liệu với lần di chuyển cuối cùng được hoàn tác, nếu không ứng dụng django sẽ không hoạt động chính xác ... Đó chỉ là một phím tắt trong dev env để đảm bảo bạn có đúng lược đồ cơ sở dữ liệu với ứng dụng hiện tại
Louis Barranqueiro

2
@LouisBarranqueiro, ý tôi là nhiều trường hợp, một DB duy nhất.
Opal,

1
Đối với bước 4, tôi muốn giới thiệu: Docker exec -ti $ CONTAINER_ID / bin / sh
Santiago Magariños

52

Tôi sử dụng phương pháp sau:

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

Sử dụng dockerphân cấp chúng tôi đã thực hiện, quá trình di chuyển dịch vụ sẽ chạy sau khi thiết lập cơ sở dữ liệu và trước khi chạy dịch vụ chính. Bây giờ khi bạn chạy dịch vụ của bạn dockersẽ chạy di chuyển trước khi chạy máy chủ; xem migrationmáy chủ đó được áp dụng trên cùng một hình ảnh của máy chủ web, điều đó có nghĩa là tất cả các quá trình di chuyển sẽ được thực hiện từ dự án của bạn, tránh các vấn đề.

Bạn tránh được việc thực hiện điểm vào hoặc bất cứ điều gì khác với cách này.


2
Làm thế nào để build: .làm việc với image: tôi nhận được lỗi mà di cư không thể kéo tên ảnh
Aaron McMillin

2
Tôi giải quyết nó bằng cách đặt build:trên migrationvì nó sẽ chạy trướcweb
Aaron McMillin

4
Điều này không giữ cho hình ảnh uzman chạy và ngốn RAM mãi mãi? Ngoài ra, những gì hình ảnh uzman?
mlissner

Đó là hình ảnh docker tùy chỉnh của tôi. Tôi chưa kiểm tra RAM.
SalahAdDin

32

Để ngăn xếp của bạn chạy sau đó bắn lệnh chạy một lần do docker-soạn. Ví dụ

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

Điều này hoạt động tốt cho cơ sở dữ liệu SQLite (mặc định) được tích hợp sẵn, nhưng cũng cho một cơ sở dữ liệu dày đặc bên ngoài được liệt kê là phụ thuộc. Đây là một tập tin docker-compos.yaml mẫu

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

Bạn có thể sử dụng docker execlệnh

docker exec -it container_id python manage.py migrate

1
Đây nên là câu trả lời.
tolga

Để nhận được container_id được đề cập, hãy thực hiện docker psvà sau đó tìm cột COMMAND cho máy chủ django.
Jai Sharma

5

Nếu bạn có một cái gì đó như thế này trong 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

Sau đó, bạn có thể đơn giản chạy ...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate

2

Tôi biết điều này đã cũ và có thể tôi đang thiếu một cái gì đó ở đây (nếu vậy, xin hãy thông cảm cho tôi!), Nhưng tại sao không chỉ thêm các lệnh vào start.shtập lệnh của bạn , do Docker chạy để kích hoạt phiên bản của bạn? Nó sẽ chỉ mất thêm vài giây.

NB Tôi đặt DJANGO_SETTINGS_MODULEbiến để đảm bảo sử dụng đúng cơ sở dữ liệu vì tôi sử dụng các cơ sở dữ liệu khác nhau để phát triển và sản xuất (mặc dù tôi biết đây không phải là 'phương pháp hay nhất').

Điều này đã giải quyết nó cho tôi:

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

Sử dụng trình điều khiển docker, tôi gặp lỗi sau:

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

Vì vậy, tôi đã sử dụng lệnh này thay thế:

docker-compose -f local.yml run django python manage.py makemigrations
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.