Я бы выбрал другой подход, чем тот, который описан здесь в других ответах.
Во-первых, Django уже предоставляет вам runserver
, который начинает легкий вес сервер разработки , который автоматически перезагружает код Python при каждом запросе. В большинстве случаев это самый простой способ запустить сервер разработки с автоматической перезагрузкой и всем остальным. Вы можете прочитать больше выше runserver
, перейдя по предоставленной ссылке. Примечание: Вы должны убедиться, что у вас есть объект приложения WSGI, заданный параметром WSGI_APPLICATION
в вашем файле конфигурации.
Вы можете запустить Django, используя команду runserver
, просто запустив bash команда типа python ./manage.py runserver 0.0.0.0:8000
. Перед запуском команды runserver
я обычно хотел бы также выполнить команду migrate
, чтобы избежать ошибок (я только что узнал об этом из опыта).
В вас docker-compose
эти команды будут выглядеть примерно так:
...
web:
...
command: >
bash -c "python ./manage.py migrate &&
./manage.py runserver 0.0.0.0:8000" # Simple bash command to run migrate followed by runserver
...
Приведенный выше код был бы идеален сам по себе, но при запуске runserver
в docker-compose
, как правило, вам придется ждать, пока ваша база данных завершит инициализацию sh, чтобы Django могла использовать ее (обсуждается позже в комментариях). Вы можете сделать это, создав простой файл в вашей директории web
с именем wait_for_db.py
и следующий код:
import os
import logging
from time import time, sleep
import MySQLdb
check_timeout = os.getenv("DB_CHECK_TIMEOUT", 30)
check_interval = os.getenv("DB_CHECK_INTERVAL", 1)
interval_unit = "second" if check_interval == 1 else "seconds"
config = {
"dbname": os.getenv("MYSQL_DATABASE", "maps_data"),
"user": os.getenv("MYSQL_USER", "chicommons"),
"password": os.getenv("MYSQL_PASSWORD", "password"),
"host": os.getenv("DATABASE_URL", "mysql")
}
start_time = time()
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
def db_isready(host, user, password, dbname):
while time() - start_time < check_timeout:
try:
conn = MySQLdb.connect(**vars())
logger.info("Database is ready! ✨")
conn.close()
return True
except Exception:
logger.info(f"Database isn't ready. Waiting for {check_interval} {interval_unit}...")
sleep(check_interval)
logger.error(f"We could not connect to the database within {check_timeout} seconds.")
return False
db_isready(**config)
Чтобы запустить указанный выше файл в вашей docker-compose
, вам потребуется чтобы обновить раздел command
, как показано ниже:
...
web:
...
command: >
bash -c "python wait_for_db.py &&
./manage.py migrate &&
./manage.py runserver 0.0.0.0:8000" # Again, note that I am simply executing a python file in a simple bash command followed by the same old migrate and runserver commands
....
Наконец, последний шаг (и, вероятно, самый важный), вам необходимо убедиться, что вы используете тома в Docker , что другие прекрасно объяснили в своих ответах здесь, но просто для ясности вот код для этого в вашем docker-compose
файле:
...
web:
...
volumes:
- ./web/:/app
# The part to the left side of the colon is the location in your computer relative to the current file, and to the left side is the location within the docker container.
# It is app because remember in your Dockerfile, you copy everything to /app directory. ;)
...
Одно последнее замечание, runserver
не должно быть выполняется на производстве. Как правило, на производстве вам не потребуется повторная загрузка в реальном времени, поэтому ваша более ранняя конфигурация для WSGI - это путь к go на производстве. Вам потребуется разделить файлы производства и разработки docker-compose
.