Docker上的Django正在启动,但浏览器给出了空响应

2024-09-29 17:44:50 发布

您现在位置:Python中文网/ 问答频道 /正文

对于在mac上使用Django、Python3和Docker的简单应用程序

Dockerfile

FROM python:3
ENV PYTHONUNBUFFERED=1

RUN mkdir /code

WORKDIR /code
COPY requirements.txt /code/
RUN python3 -m pip install -r requirements.txt
CMD python3 manage.py runserver  

COPY . /code/

docker-compose.yml

version: "3.9"

services:
  # DB
  db:
    image: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: '****'
      MYSQL_USER: '****'
      MYSQL_PASSWORD: '****'
      MYSQL_DATABASE: 'mydb'
    ports:
      - "3307:3306"
    expose:
      # Opens port 3306 on the container
      - '3307'
    volumes:
      - $HOME/proj/sql/mydbdata.sql:/mydbdata.sql

  # Web app
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

另外,我想要的是在第一次创建映像时执行SQL, 之后,应该装入数据库

    volumes:
  - $HOME/proj/sql/mydbdata.sql:/mydbdata.sql

看起来Docker正在启动,但从我的浏览器中,我得到了以下响应

localhost didn’t send any data.
ERR_EMPTY_RESPONSE

我错过了什么。请帮忙


Tags: dockerrunpytxtdbsqlmanagemysql
1条回答
网友
1楼 · 发布于 2024-09-29 17:44:50

创建映像时,django项目似乎已在运行。由于您使用了command选项docker-compose.yml文件,因此在本例中Dockerfile中不需要CMD命令

我将Dockerfiledocker-compose.yml改写如下:

FROM python:3
ENV PYTHONUNBUFFERED 1

RUN mkdir /code

WORKDIR /code
COPY requirements.txt /code/
RUN python3 -m pip install -r requirements.txt

COPY . /code/
version: "3.9"

services:
  db:
    image: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: '****'
      MYSQL_USER: '****'
      MYSQL_PASSWORD: '****'
      MYSQL_DATABASE: 'mydb'
    ports:
      - "3307:3306"  # make sure django project connects to 3306 port  
    volumes:
      - $HOME/proj/sql:/docker-entrypoint-initdb.d

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

有几件事需要指出

  1. 当您运行docker-compose up时,您可能会看到一个错误,因为您的django项目甚至在初始化db之前就已经在运行了。 这很自然。所以您需要自定义命令或shell程序来强制django项目等待尝试连接db

在我的情况下,我将使用自定义命令

version: "3.9"

services:

  db:
    image: mysql:8
    env_file:
      - .env
    command: 
      -  default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - "3308:3306"

  web:
    build: .
    command: >
      sh -c "python manage.py wait_for_db &&
             python manage.py makemigrations && 
             python manage.py migrate && 
             python manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "8001:8000"
    depends_on: 
      - db
    env_file:
      - .env

接下来,wait_for_db.py。这个文件是我在myapp/management/commands/wait_for_db.py中创建的。通过这种方式,您可以推迟db连接,直到db就绪。这对我帮助很大

详情见Writing custom django-admin command

import time

from django.db import connection
from django.db.utils import OperationalError
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    """Wait to connect to db until db is initialised"""

    def handle(self, *args, **options):
        start = time.time()
        self.stdout.write('Waiting for database...')
        while True:
            try:
                connection.ensure_connection()
                break
            except OperationalError:
                time.sleep(1)

        end = time.time()
        self.stdout.write(self.style.SUCCESS(f'Database available! Time taken: {end-start:.4f} second(s)'))
  1. 看起来您希望在db容器开始运行时使用sql文件填充数据库Mysql docker hub says

Initializing a fresh instance When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.

因此.sql文件应该位于mysql容器的/docker-entrypoint-initdb.d中。有关更多信息,请参见this post

  1. 最后但并非最不重要的一点是,当您运行docker-compose down时,您的数据库将丢失,因为您没有sql文件以外的卷。这不是你想要的,你可能想考虑下面的
version: "3.9"

services:

  db:
...
    volumes:
      - data:/var/lib/mysql

...

volumes:
  data:

相关问题 更多 >

    热门问题