首页 > 解决方案 > 无法使用 Flask 和 Flask Migrate 在 Docker 中运行入口点脚本,即使它可以在终端中运行

问题描述

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

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

我在Miguel Grinberg 的 Docker 部署教程中看到,这可以通过将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命令,这实际上会发生。

奇怪的是:

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

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

RUN flask db upgrade

Dockerfile

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"]

标签: pythondockerflaskshflask-migrate

解决方案


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

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

我的主要问题是我的目录中的文件夹结构不一致。有 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"]为just["./boot.sh"]
  • 将迁移文件移动到升级脚本的相关文件夹中

然后我能够在入口点文件中激活虚拟环境,并运行烧瓶升级命令(注意:我遇到了行结尾是 CRLF 而不是 LF in 的问题boot.sh,所以如果在 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)中使用一些库时,这是一个非常成熟的问题。

我切换到 Debian 构建,以便我可以更快地对我的 Docker 映像进行更改。

包括安装 pyodbc 以连接到 Azure SQL Server,我的 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

以下curl命令来自官方 MS 文档,关于在 Debian 上安装 pyodbc

完整的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"]

推荐阅读