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

Docker撰写获得mysql db完全启动之前烧瓶应用程序启动

公羊宗清
2023-03-14

我刚开始对我的应用程序进行dockerize。我已经建立了我的Dockerfiledockercompose.yml,除了一件事之外,一切似乎都很好。有时我的flask应用程序启动太快,抛出连接被拒绝错误(因为MySQL数据库没有完全启动)。我正在使用healthcheck检查数据库是否启动,但这似乎不可靠(我甚至确保可以看到show databases,但mysql显然在healthcheck通过后初始化了更多内容?不确定healthcheck用于什么)。在我的输出中,我看到db确实是先创建的,但当flask应用程序启动时,它仍在初始化。理想情况下,当我运行docker compose up时,我希望能够首先看到这一行,

db_1_eae741771281 | 2018-11-10T00:50:21.473098Z 0 [Note] mysqld: ready for connections.

然后启动我的烧瓶应用程序切入点。目前,它没有这样做。

在启动我的start.sh之前,有没有更可靠的方法来确保MySQL完全启动?

Dockerfile:

FROM python:3.5-alpine

RUN apk update && apk upgrade

RUN apk add --no-cache curl python build-base openldap-dev python2-dev python3-dev pkgconfig python-dev libffi-dev musl-dev make gcc

RUN pip install --upgrade pip

RUN adduser -D user

WORKDIR /home/user

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt

COPY app app
COPY start.sh ./
RUN chmod +x start.sh

RUN chown -R user:user ./
USER user

EXPOSE 5000
ENTRYPOINT ["./start.sh"]

docker-compose.yml:

version: "2.1"
services:
  db:
    image: mysql:5.7
    ports:
      - "32000:3306"
    environment:
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=user
      - MYSQL_PASSWORD=user123
      - MYSQL_ROOT_PASSWORD=user123
    volumes:
      - ./db:/docker-entrypoint-initdb.d/:ro
    healthcheck:
            test: "mysql --user=user --password=user123 --execute \"SHOW DATABASES;\""
            timeout: 20s
            retries: 20

  app:
    build: ./
    ports:
      - "5000:5000"
    depends_on:
      db:
        condition: service_healthy

start.sh

#!/bin/sh

source venv/bin/activate
# Start Gunicorn processes
echo Starting Gunicorn.

exec gunicorn -b 0.0.0.0:5000 wsgi --chdir my_app --timeout 9999 --workers 3 --access-logfile - --error-logfile - --capture-output --log-level debug

共有3个答案

濮阳立果
2023-03-14

这是多容器的常见问题。很难控制不同容器的启动速度。在这种情况下,像Kubernetes这样的容器编排解决方案可能会对您有所帮助。Kubernetes有init容器的概念,它在依赖容器启动之前运行到完成。您可以在这里找到init容器的示例

https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html

这个youtube视频可能对你也有帮助https://www.youtube.com/watch?v=n2FPsunhuFc

尹昂雄
2023-03-14

虽然使用健康检查更容易,但这完全取决于检查的可靠性。

另一种方法是依赖应用程序容器中的项目,如等待它等待
由于您的连接被拒绝,这些脚本只能在连接成功后返回,并且您的应用程序只能在连接成功后启动。

此外,如果这也不起作用,您可以使用单独的脚本(在您的示例中是python)进行检查,直到DB就绪,并且您可以在启动flask应用程序之前在start.sh中调用此脚本。

仲孙绍元
2023-03-14

好的,我的健康检查也有问题。。。

也许不是最理想的,但最可靠的解决方案是在启动应用程序之前使用MySQL客户端(mysqladmin)来ping您的MySQL服务器。

1-创建wait.sh脚本(db是您的MySQL服务名称):

#!/bin/sh

# Wait until MySQL is ready
while ! mysqladmin ping -h"db" -P"3306" --silent; do
    echo "Waiting for MySQL to be up..."
    sleep 1
done

2-从你的appDockerfile获取MySQL客户端:

# install mysql client, will be used to ping mysql
apt-get -y install mysql-client

3-在您的docker compose.yml文件中,只需将脚本添加到您的容器中(我使用了卷,但您可以继续使用COPY),然后在start.sh之前运行wait.sh

app:
    build: ./
    ports:
      - "5000:5000"
    depends_on:
      db:
    command: bash -c "/usr/local/bin/wait.sh && /usr/local/bin/start.sh"
    volumes:
      - ./start.sh:/usr/local/bin/start.sh
      - ./wait.sh:/usr/local/bin/wait.sh

这应该行得通。

如果您真的不想下载MySQL客户端,请尝试此操作(这里的MySQL服务名称是db)。它在我的大部分项目中都有效,但并非全部有效(可能取决于分布情况):

#!/bin/sh

# Wait until MySQL is ready
while ! exec 6<>/dev/tcp/db/3306; do
    echo "Trying to connect to MySQL at 3306..."
    sleep 5
done

注意:避免将您的服务命名为“app”或“db”,如果您有其他具有相同服务名称的容器(即使在不同的网络中),以后可能会出现问题。

 类似资料:
  • 我有一个烧瓶应用程序,我正试图过渡到通过gunicorn运行。我在这方面遇到了很多问题。以下是我的应用程序的运行代码: 首先,如果DEBUG_FLAG==true,应用程序将永远不会真正启动,但会继续重新启动,在本地点击它将不起作用。它只是一次又一次地这样做: 如果我用DEBUG_FLAG==False启动它,它实际上会启动并服务于一些请求,但由于未知原因,它仍然会频繁中断并重新启动: 如前所述,

  • 我正在尝试发布我的第一个Android应用程序,以发送给一些测试人员。但是,我遇到了一个问题。当您退出应用程序,然后通过其图标启动它重新进入它时,它会重新启动整个应用程序,而不是返回到其以前的位置。即使您在退出后立即重新进入,也会发生这种情况。但是,如果我按住主屏幕按钮并通过最近的应用程序列表启动它,则不会发生这种情况。 我在网上搜索过其他有这个问题的人,只有少数人,但没有人能确切回答为什么会发生

  • 我们的webstart应用程序(不是小程序)遇到了奇怪的启动问题。 启动应用程序会显示应用程序启动屏幕,但javaws进程会在不久后终止,不会在对话框、java控制台或日志文件中显示任何错误消息。javaws似乎只是在实际启动实际应用程序之前停止。无论用户尝试从桌面快捷方式还是从网页启动应用程序,都无关紧要。当从本地计算机使用javaw运行而无需webstart时,相同的应用程序可以正常工作。 应

  • 我尝试使用Flask制作一个小应用程序,但经常需要重新启动应用程序才能看到结果,这是一种过分的做法。 是否有任何设置可以简单地更新应用程序而不重新启动?(类似于任何像样的PHP或Java/JSP应用程序) [编辑]通过将标志调试设置为True,应用程序的重启可以是手动的或自动的。在这两种情况下,应用程序都会重新启动。我对应用程序的无启动/重新启动感兴趣-不是手动或自动的。 最好的例子是一个PHP页

  • 问题内容: 我有一个Java应用程序。 该应用程序具有一个设置,该设置决定该应用程序是否在启动时启动。 目前,我可以通过在“启动项目”文件夹中放置/删除快捷方式来实现此目的。 但是,我想知道是否有更好的方法来处理此行为。 编辑 是的,它是Windows。抱歉,之前没有清除该内容。 该应用程序具有一个用户可以在其中触发动作的UI,并且该应用程序在运行时会定期在后台运行一些任务。 @Peter,如何在

  • 它永远不会结束,应用程序也不会响应: 我已经检查了以下几点: 我的应用程序扩展了SpringBootServletInitializer 我将初学者tomcat依赖项放在提供的中 war名为“EdgeCustomerOfferStorageWeb.war”,实例端口为10080,因此我使用:http://server:10080/EdgeCustomerOfferStorageWeb/It不响应,