我刚开始对我的应用程序进行dockerize。我已经建立了我的Dockerfile
和dockercompose.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
这是多容器的常见问题。很难控制不同容器的启动速度。在这种情况下,像Kubernetes这样的容器编排解决方案可能会对您有所帮助。Kubernetes有init容器的概念,它在依赖容器启动之前运行到完成。您可以在这里找到init容器的示例
https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html
这个youtube视频可能对你也有帮助https://www.youtube.com/watch?v=n2FPsunhuFc
虽然使用健康检查更容易,但这完全取决于检查的可靠性。
另一种方法是依赖应用程序容器中的项目,如等待它
或等待
。
由于您的连接被拒绝,这些脚本只能在连接成功后返回,并且您的应用程序只能在连接成功后启动。
此外,如果这也不起作用,您可以使用单独的脚本(在您的示例中是python)进行检查,直到DB就绪,并且您可以在启动flask应用程序之前在start.sh
中调用此脚本。
好的,我的健康检查也有问题。。。
也许不是最理想的,但最可靠的解决方案是在启动应用程序之前使用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-从你的app
Dockerfile获取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不响应,