当前位置: 首页 > 知识库问答 >
问题:

docker-comment不能等待mysql数据库

郝永思
2023-03-14

我有真正的问题,试图得到一个docker-comment脚本来启动一个mysql数据库和一个Django项目,但是让Django项目等到mysql数据库准备好。

我有两个文件,一个Dockerfile和一个docker-compose.yml,我在下面复制了它们。

当我运行docker-compose.yml并检查web容器的日志时,它说它无法连接到数据库mydb。然而,我第二次运行它(没有清除容器和图像)时,它正确连接,Django应用程序正常工作。

我花了一整天的时间尝试了很多事情,比如脚本、健康检查等等,但是我无法让它工作。

Dockerfile

FROM python:3.6

ENV PYTHONUNBUFFERED 1

RUN mkdir /code
WORKDIR /code

COPY ./ /code/

RUN pip install -r requirements.txt
RUN python manage.py collectstatic --noinput

docker-compose.yml

version: '3'

services:
  mydb:
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_USER=django
      - MYSQL_PASSWORD=secret
      - MYSQL_DATABASE=dbMarksWebsite
    image: mysql:5.7
    ports:
      # Map default mysql port 3306 to 3308 on outside so that I can connect
      # to mysql using workbench localhost with port 3308
      - "3308:3306"
  web:
    environment:
      - DJANGO_DEBUG=1
      - DOCKER_PASSWORD=secret
      - DOCKER_USER=django
      - DOCKER_DB=dbMarksWebsite
      - DOCKER_HOST=mydb
      - DOCKER_PORT=3306
    build: .
    command: >
      sh -c "sleep 10 &&
             python manage.py migrate &&
             python manage.py loaddata myprojects_testdata.json &&
             python manage.py runserver 0.0.0.0:8080"
    ports:
      - "8080:8080"
    depends_on:
      - mydb

第一次运行(没有现有图像或容器):

...
  File "/usr/local/lib/python3.6/site-packages/MySQLdb/__init__.py", line 84, in Connect
    return Connection(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/MySQLdb/connections.py", line 179, in __init__
    super(Connection, self).__init__(*args, **kwargs2)
django.db.utils.OperationalError: (2002, "Can't connect to MySQL server on 'mydb' (115)")

第二轮:

System check identified no issues (0 silenced).
March 27, 2020 - 16:44:57
Django version 2.2.11, using settings 'ebdjango.settings'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.

共有3个答案

白淇
2023-03-14

我在entrypoint.sh中使用以下函数解决了它:

function wait_for_db()
{
  while ! ./manage.py sqlflush > /dev/null 2>&1 ;do
    echo "Waiting for the db to be ready."
    sleep 1
  done
}
辛星宇
2023-03-14

出于测试/开发目的,您可以使用具有运行状况检查的MySQL映像版本(我相信有一个healthcheck/MySQLimage),或者配置您自己的映像版本(参见这里的示例:Docker compose check if MySQL connection is ready)。

对于生产使用,您不想在启动时升级数据库模式,也不想假设数据库已启动。升级模式会自动鼓励您不要考虑部署错误并需要回滚时会发生什么,并行模式升级也不会起作用。较长版本:https://pythonspeed.com/articles/schema-migrations-server-startup/

姜晨
2023-03-14

对于任何感兴趣的人,我找到了一个解决方案:

1-我编写了一个python脚本,每秒连接一次数据库,但有一个超时。我将此超时设置为60秒,但在我的计算机上似乎可以正常工作。

2-我在我的撰写文件中添加了等待命令。

这应该意味着我可以为我的网站调出一组测试容器,在那里我可以指定所使用的Python和MySQL的确切版本。

相关文件如下所示:

Dockerfile:

FROM python:3.6

ENV PYTHONUNBUFFERED 1

RUN mkdir /code
WORKDIR /code

COPY ./ /code/

RUN pip install -r requirements.txt
RUN python manage.py collectstatic --noinput

docker-compose.yml

version: '3'

services:
  mydb:
    container_name: mydb
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_USER=django
      - MYSQL_PASSWORD=secret
      - MYSQL_DATABASE=dbMarksWebsite
    image: mysql:5.7
    ports:
      # Map default mysql port 3306 to 3308 on outside so that I can connect
      # to mysql using workbench localhost with port 3308
      - "3308:3306"
  web:
    container_name: web
    environment:
      - DJANGO_DEBUG=1
      - DOCKER_PASSWORD=secret
      - DOCKER_USER=django
      - DOCKER_DB=dbMarksWebsite
      - DOCKER_HOST=mydb
      - DOCKER_PORT=3306
    build: .
    command: >
      sh -c "python ./bin/wait-for.py mydb 3306 django secret dbMarksWebsite 60  &&
             python manage.py migrate &&
             python manage.py loaddata myprojects_testdata.json &&
             python manage.py runserver 0.0.0.0:8080"
    ports:
      - "8080:8080"
    depends_on:
      - mydb

等待

'''
I don't like adding this in here, but I cannot get the typical wait-for scripts
to work with MySQL database in docker, so I hve written a python script that
either times out after ? seconds or successfully connects to the database
The input arguments for the script need to be:

    HOST, PORT, USERNAME, PASSWORD, DATABASE, TIMEOUT

'''
import sys, os
import time
import pymysql

def readCommandLineArgument():
    '''
    Validate the number of command line input arguments and return the
    input filename
    '''

    # Get arguments
    if len(sys.argv)!=7:
        raise ValueError("You must pass in 6 arguments, HOST, PORT, USERNAME, PASSWORD, DATABASE, TIMEOUT")

    # return the arguments as a tuple
    return (sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6]) 

def connectToDB(HOST, PORT, USERNAME, PASSWORD, DATABASE):
    '''
    for now, just try to connect to the database.
    '''

    con = pymysql.connect(host=HOST, port=PORT, user=USERNAME, password=PASSWORD, database=DATABASE)

    with con:
        cur = con.cursor()
        cur.execute("SELECT VERSION()")

def runDelay():
    '''
    I don't like passing passwords in, but this is only used for a test docker
    delay script
    '''

    # Get the database connection characteristics.
    (HOST, PORT, USERNAME, PASSWORD, DATABASE, TIMEOUT) = readCommandLineArgument()

    # Ensure timeout is an integer greater than zero, otherwise use 15 secs a default
    try:
        TIMEOUT = int(TIMEOUT)
        if TIMEOUT <= 0:
            raise("Timeout needs to be > 0")
    except:
        TIMEOUT = 60

    # Ensure port is an integer greater than zero, otherwise use 3306 as default
    try:
        PORT = int(PORT)
        if PORT <= 0:
            raise("Port needs to be > 0")
    except:
        PORT = 3306

    # Try to connect to the database TIMEOUT times
    for i in range(0, TIMEOUT):

        try:
            # Try to connect to db
            connectToDB(HOST, PORT, USERNAME, PASSWORD, DATABASE)

            # If an error hasn't been raised, then exit
            return True

        except Exception as Ex:
            strErr=Ex.args[0]
            print(Ex.args)
            # Sleep for 1 second
            time.sleep(1)

    # If I get here, assume a timeout has occurred
    raise("Timeout")


if __name__ == "__main__":

    runDelay()
 类似资料:
  • 我正在尝试将数据库调用移出控制器,以清理并使其可测试。当它们在控制器中时,一切都会顺利进行。我将它们移出控制器,并添加了一个异步,以确保我们等待。否则,我将调用的中的函数。现在,一旦我使用async/await,控制器中的函数就会认为没有用户,因为它没有等待。 有几个关于异步等待的SO问题,但我没有找到一个解决我的问题。我确实验证了返回了我的用户,并添加了控制台日志来显示路径。 节点猫鼬异步等待似

  • 问题内容: 我在项目中将Django与PostgreSQL一起使用。我把它们放在不同的容器中,问题是我需要在运行django之前等待postgres。这时我正在用django容器的command.sh文件执行此操作。我还发现netcat可以解决问题,但是我更喜欢没有附加软件包的方法。curl和wget无法执行此操作,因为它们不支持postgres协议。有办法吗? 问题答案: 您的解决方案tizia

  • 问题内容: 情况如下: 我有一个泊坞窗容器(jenkins)。我已经将套接字安装到容器中,以便可以在jenkins容器中执行docker命令。 手动操作,一切都在容器中进行。但是,当詹金斯执行作业时,它不会“等待” 命令运行完成。 下面是Jenkinsfile的摘录。短期命令可以正确运行,并输出环境变量。仅运行下一个命令(python),然后Jenkins立即继续前进,而无需等待完成。Jenkin

  • 我正试图将图像上传到firebase存储,但调用该函数时,未执行wait以获取url。我错过了什么? 看看这个其他主题,我发现问题可能是“然后”,但我如何设置代码以等待url? 异步/等待/然后飞镖/颤振 谢谢

  • 我想在docker容器中安排一个作业。首先,在环顾四周之后,我可以正确地建立集装箱时区。当我在终端中使用“date”命令时,它会显示我所在城市和国家的小时数,但cronjob会使用默认情况下在容器中指定的时区。我读到有必要告诉克朗,时区已经改变了。我尝试了使用环境变量TZ_CRON,但它不起作用。我还重新启动了容器内的cron服务,但它仍以相同的方式工作。 我的代码基于此回购协议https://g

  • 在Windows上使用Workbase客户端(v6.3.5 x64)的最新副本,我试图从我的MySQL数据库创建一个转储文件,但总是只得到一个0~1Ko的转储文件。我在具有相同版本的两台服务器上尝试过,我得到了相同的结果: < li >执行任务时出错:“ascii”编解码器无法对位置7中的字符u'\xa3 '进行编码:序号不在范围(128)内 < li >执行任务时出错[错误32]该进程无法访问该