使用 Docker-Compose 时如何执行 Django 数据库迁移?
How do you perform Django database migrations when using Docker-Compose?
我在 Django Quick Start instructions on the Docker site 之后设置了一个 Docker Django/PostgreSQL 应用程序。
我第一次 运行 Django 的 manage.py 迁移,使用命令 sudo docker-compose run web python manage.py migrate
,它按预期工作。数据库建在 Docker PostgreSQL 容器中就好了。
对 Django 应用程序本身所做的更改同样反映在 Docker Django 容器中,在我保存它们的那一刻。太棒了!
但是如果我随后在 Django 中更改模型,并尝试更新 Postgres 数据库以匹配该模型,则不会检测到任何更改,因此无论我 运行 [=12= 多少次都不会发生迁移] 或再次 migrate
。
基本上,每次我更改 Django 模型时,我都必须删除 Docker 个容器(使用 sudo docker-compose rm
)并重新开始新的迁移。
我仍在努力思考 Docker,而且有很多我不明白它是如何工作的,但这一个让我抓狂。为什么迁移看不到我的更改?我做错了什么?
您只需登录 运行ning docker 容器并 运行 您的命令。
- 建立你的堆栈:
docker-compose build -f path/to/docker-compose.yml
- 启动您的堆栈:
docker-compose up -f path/to/docker-compose.yml
- 显示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 ...
- 获取 django 应用程序的 CONTAINER ID 并登录:
docker exec -t -i 66175bfd6ae6 bash
现在您已登录,然后转到正确的文件夹:cd path/to/django_app
现在,每次编辑模型时,运行 在容器中:python manage.py makemigrations
和 python manage.py migrate
我还建议您使用 docker-入口点将 django docker 容器文件自动 运行 :
- collecstatic
- 迁移
- 运行server 或用 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
我使用这些方法:
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 服务器相同的图像上,这意味着所有迁移都将从您的项目中获取,避免出现问题。
你可以用这种方式避免创建入口点或任何其他东西。
让你的堆栈 运行ning 然后发射单发 docker-compose 运行 命令。例如
#assume django in container named web
docker-compose run web python3 manage.py migrate
这适用于 built-in(默认)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
您可以使用docker exec
命令
docker exec -it container_id python manage.py migrate
我知道这是旧的,也许我在这里遗漏了一些东西(如果是这样,请赐教!),但为什么不直接将命令添加到您的 start.sh
脚本中,运行 Docker 启动您的实例?只需多花几秒钟。
N.B. 我设置 DJANGO_SETTINGS_MODULE
变量以确保使用正确的数据库,因为我使用不同的数据库进行开发和生产(尽管我知道这不是 'best practice').
这为我解决了:
#!/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
使用 docker exec,我收到以下错误:
AppRegistryNotReady("Models aren't loaded yet.")
所以我改用这个命令:
docker-compose -f local.yml run django python manage.py makemigrations
如果您的 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
您可以使用 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
如果只想使用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"]
我在 Django Quick Start instructions on the Docker site 之后设置了一个 Docker Django/PostgreSQL 应用程序。
我第一次 运行 Django 的 manage.py 迁移,使用命令 sudo docker-compose run web python manage.py migrate
,它按预期工作。数据库建在 Docker PostgreSQL 容器中就好了。
对 Django 应用程序本身所做的更改同样反映在 Docker Django 容器中,在我保存它们的那一刻。太棒了!
但是如果我随后在 Django 中更改模型,并尝试更新 Postgres 数据库以匹配该模型,则不会检测到任何更改,因此无论我 运行 [=12= 多少次都不会发生迁移] 或再次 migrate
。
基本上,每次我更改 Django 模型时,我都必须删除 Docker 个容器(使用 sudo docker-compose rm
)并重新开始新的迁移。
我仍在努力思考 Docker,而且有很多我不明白它是如何工作的,但这一个让我抓狂。为什么迁移看不到我的更改?我做错了什么?
您只需登录 运行ning docker 容器并 运行 您的命令。
- 建立你的堆栈:
docker-compose build -f path/to/docker-compose.yml
- 启动您的堆栈:
docker-compose up -f path/to/docker-compose.yml
- 显示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 ...
- 获取 django 应用程序的 CONTAINER ID 并登录:
docker exec -t -i 66175bfd6ae6 bash
现在您已登录,然后转到正确的文件夹:
cd path/to/django_app
现在,每次编辑模型时,运行 在容器中:
python manage.py makemigrations
和python manage.py migrate
我还建议您使用 docker-入口点将 django docker 容器文件自动 运行 :
- collecstatic
- 迁移
- 运行server 或用 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
我使用这些方法:
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 服务器相同的图像上,这意味着所有迁移都将从您的项目中获取,避免出现问题。
你可以用这种方式避免创建入口点或任何其他东西。
让你的堆栈 运行ning 然后发射单发 docker-compose 运行 命令。例如
#assume django in container named web
docker-compose run web python3 manage.py migrate
这适用于 built-in(默认)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
您可以使用docker exec
命令
docker exec -it container_id python manage.py migrate
我知道这是旧的,也许我在这里遗漏了一些东西(如果是这样,请赐教!),但为什么不直接将命令添加到您的 start.sh
脚本中,运行 Docker 启动您的实例?只需多花几秒钟。
N.B. 我设置 DJANGO_SETTINGS_MODULE
变量以确保使用正确的数据库,因为我使用不同的数据库进行开发和生产(尽管我知道这不是 'best practice').
这为我解决了:
#!/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
使用 docker exec,我收到以下错误:
AppRegistryNotReady("Models aren't loaded yet.")
所以我改用这个命令:
docker-compose -f local.yml run django python manage.py makemigrations
如果您的 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
您可以使用 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
如果只想使用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"]