无法使用 Flask 和 Flask Migrate 在 Docker 中 运行 入口点脚本,即使它在终端中工作

Cannot run entrypoint script in Docker with Flask and Flask Migrate, even though it works in Terminal

我有一个连接到 Azure SQL 数据库的 Flask API,部署在 Docker 映像中的 Azure 应用服务上。

它工作正常,但我正在尝试使用 Alembic/Flask-Migrate 应用数据库升级来保持我的开发、暂存和生产环境之间的一致性。

我在 Miguel Grinberg's Docker Deployment Tutorial 上看到,这可以通过将 flask db upgrade 命令添加到 boot.sh 脚本来实现,如下所示:

#!/bin/sh
flask db upgrade
exec gunicorn -w 4 -b :5000 --access-logfile - --error-logfile - app:app

我的问题是,当 运行 运行 boot.sh 脚本时,我收到错误消息:

Usage: flask db [OPTIONS] COMMAND [ARGS]...
Try 'flask db --help' for help.

'.ror: No such command 'upgrade

这表示脚本找不到 Flask-Migrate 库。如果我尝试其他站点包,例如只是尝试 运行 flask 命令,这实际上会发生。

奇怪的是:

显然,我的 Docker 文件有问题。我非常感谢这里的任何帮助,因为我对 Docker 和 Linux 比较陌生,所以我确定我遗漏了一些明显的东西:

编辑:如果我将以下行添加到我的 Docker 文件中,就在入口点 CMD 之前,它也可以正常工作:

RUN flask db upgrade

Docker文件

FROM python:3.8-alpine

# Dependencies for pyodbc on Linux
RUN apk update
RUN apk add curl sudo build-base unixodbc-dev unixodbc freetds-dev
RUN apk add gcc musl-dev libffi-dev openssl-dev
RUN apk add --no-cache tzdata
RUN rm -rf /var/cache/apk/*
RUN curl -O https://download.microsoft.com/download/e/4/e/e4e67866-dffd-428c-aac7-8d28ddafb39b/msodbcsql17_17.5.2.2-1_amd64.apk
RUN sudo sudo apk add --allow-untrusted msodbcsql17_17.5.2.2-1_amd64.apk

RUN mkdir /code
WORKDIR /code

COPY requirements.txt requirements.txt
RUN python -m pip install --default-timeout=100 -r requirements.txt
RUN python -m pip install gunicorn
ADD . /code/

COPY boot.sh /usr/local/bin/    
RUN chmod u+x /usr/local/bin/boot.sh
EXPOSE 5000
ENTRYPOINT ["sh", "boot.sh"]

我认为这是关键信息。

Which indicates the script cannot find the Flask-Migrate library. This actually happens if I try other site-packages, such as just trying to run flask commands.

对我来说,这可能表明问题并非特定于 Flask-Migrate,而是针对所有包 - 如您所写。这可能意味着以下两个中的一个。

首先,这可能意味着软件包没有正确安装。但是,这不太可能,因为您写道它在您 手动 启动容器时有效。

其次,您执行 boot.sh 脚本的方式有问题。例如,尝试更改

ENTRYPOINT ["sh", "boot.sh"]

ENTRYPOINT ["/bin/sh", "boot.sh"]

HTH!

我最终对 Docker 文件和 boot.sh 脚本进行了一些重大更改。我将尽我所能在下面分享这些内容:

问题 1:入口点脚本无法访问目录

我的主要问题是我的目录中的文件夹结构不一致。有 2 个 boot.sh 脚本,入口点上的 运行 要么权限错误,要么在错误的位置找到我的网站包。

我简化了将文件从本地计算机复制到 Docker 映像的过程,如下所示:

RUN mkdir /code
WORKDIR /code

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install --default-timeout=100 -r requirements.txt
RUN venv/bin/pip install gunicorn

COPY app app
COPY migrations migrations
COPY api.py config.py boot.sh ./
RUN chmod u+x boot.sh

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

涉及的变化:

  • 正在设置 virtualenv 并在其中安装所有站点包
  • 确保 config.pyboot.shapi.py 文件位于应用程序文件夹的根目录中 (./)
  • 将入口点命令从 ["bin/sh", "boot.sh"] 更改为仅 ["./boot.sh"]
  • 将迁移文件移动到升级脚本的相关文件夹中

然后我能够在入口点文件中激活虚拟环境,并且 运行 flask 升级命令(注意:我在 boot.sh 中行结尾是 CRLF 而不是 LF 时遇到问题, 因此请确保在 Windows):

上更改它
#!/bin/bash
source venv/bin/activate
flask db upgrade
exec gunicorn -w 4 -b :5000 --access-logfile - --error-logfile - api:app

问题 2:Alpine Linux 太慢

我的另一个问题是我的图像在 Alpine Linux 上需要很长时间才能构建(超过 45 分钟)。在我的 API (Pandas, Numpy) 中使用一些库时发现这是 pretty well-established issue

我切换到 Debian 版本以便我可以更快地更改我的 Docker 图像。

包括安装 pyodbc 以连接到 Azure SQL 服务器,我的 Docker 文件的前半部分现在看起来像:

FROM python:3.8-slim-buster

RUN apt-get update
RUN apt-get install -y apt-utils curl sudo gcc g++ gnupg2

RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get install -y libffi-dev libgssapi-krb5-2 unixodbc-dev unixodbc freetds-dev 
RUN sudo apt-get update
RUN sudo ACCEPT_EULA=Y apt-get install msodbcsql17
RUN apt-get clean -y

curl 命令及以下来自 the official MS docs on installing pyodbc on Debian

完整的 dockerfile:

FROM python:3.8-slim-buster

RUN apt-get update
RUN apt-get install -y apt-utils curl sudo gcc g++ gnupg2
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get install -y libffi-dev libgssapi-krb5-2 unixodbc-dev unixodbc freetds-dev 
RUN sudo apt-get update
RUN sudo ACCEPT_EULA=Y apt-get install msodbcsql17
RUN apt-get clean -y

RUN mkdir /code
WORKDIR /code

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install --default-timeout=100 -r requirements.txt
RUN venv/bin/pip install gunicorn

COPY app app
COPY migrations migrations
COPY api.py config.py boot.sh ./
RUN chmod u+x boot.sh

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