如何在 Ubuntu 18.04 上使用 Docker 构建和部署 Flask 应用程序

作为Write for DOnations计划的一部分,作者选择了技术教育基金来接受捐赠

介绍

Docker是一个开源应用程序,允许管理员使用容器创建、管理、部署和复制应用程序。容器可以被认为是一个包,其中包含应用程序在操作系统级别运行所需的依赖项。这意味着使用 Docker 部署的每个应用程序都存在于自己的环境中,并且其需求是单独处理的。

Flask是一个基于Python的 Web 微框架之所以称为微框架,是因为它不需要特定的工具或插件即可运行。Flask 框架是轻量级和灵活的,但高度结构化,使其优于其他框架。

使用 Docker 部署 Flask 应用程序将允许您以最少的重新配置跨不同服务器复制应用程序。

在本教程中,您将创建一个 Flask 应用程序并使用 Docker 部署它。本教程还将介绍如何在部署后更新应用程序。

先决条件

要遵循本教程,您将需要以下内容:

第 1 步 – 设置 Flask 应用程序

首先,您将创建一个目录结构来保存您的 Flask 应用程序。本教程将创建一个名为TestAppin的目录/var/www,但您可以修改该命令以将其命名为您喜欢的任何名称。

  • sudo mkdir /var/www/TestApp

移动到新创建的TestApp目录:

  • cd /var/www/TestApp

接下来,为 Flask 应用程序创建基本文件夹结构:

  • sudo mkdir -p app/static app/templates

-p标志表示mkdir将创建一个目录和所有不存在的父目录。在这种情况下,mkdirapp在制作statictemplates目录的过程中创建目录。

app目录将包含与 Flask 应用程序相关的所有文件,例如其视图蓝图视图是您为响应对应用程序的请求而编写的代码。蓝图创建应用程序组件并支持应用程序内或跨多个应用程序的通用模式。

static目录是图像、CSS 和 JavaScript 文件等资产所在的位置。templates目录是您将放置项目的 HTML 模板的位置。

现在基本文件夹结构已完成,创建运行 Flask 应用程序所需的文件。首先,__init__.pyapp目录中创建一个文件这个文件告诉 Python 解释器该app目录是一个包,应该这样对待。

运行以下命令来创建文件:

  • sudo nano app/__init__.py

Python 中的包允许您将模块分组到逻辑命名空间或层次结构中。这种方法使代码能够分解为执行特定功能的单个和可管理的块。

接下来,您将添加代码以__init__.py创建 Flask 实例并从views.py文件中导入逻辑,您将在保存此文件后创建该文件。将以下代码添加到您的新文件中:

/var/www/TestApp/app/__init__.py
from flask import Flask
app = Flask(__name__)
from app import views

添加该代码后,保存并关闭文件。

随着__init__.py创建的文件,你可以创建views.py在您的文件app目录。此文件将包含您的大部分应用程序逻辑。

  • sudo nano app/views.py

接下来,将代码添加到您的views.py文件中。此代码会将hello world!字符串返回给访问您网页的用户:

/var/www/TestApp/app/views.py
from app import app

@app.route('/')
def home():
   return "hello world!"

@app.route功能上面的行被称为装饰装饰器修改它后面的函数。在这种情况下,装饰器告诉 Flask 哪个 URL 将触发该home()函数。函数hello world返回文本home将在浏览器上显示给用户。

随着views.py在地方文件,你可以创建uwsgi.ini文件。该文件将包含我们应用程序uWSGI配置。uWSGI 是 Nginx 的部署选项,既是协议又是应用服务器;应用服务器可以为 uWSGI、FastCGI 和 HTTP 协议提供服务。

要创建此文件,请运行以下命令:

  • sudo nano uwsgi.ini

接下来,将以下内容添加到您的文件中以配置 uWSGI 服务器:

/var/www/TestApp/uwsgi.ini
[uwsgi]
module = main
callable = app
master = true

此代码定义了 Flask 应用程序将从中提供服务的模块。在本例中,这是该main.py文件,此处引用为main. callable选项指示 uWSGI 使用app主应用程序导出实例。master选项允许您的应用程序继续运行,因此即使重新加载整个应用程序也几乎没有停机时间。

接下来,创建main.py文件,它是应用程序的入口点。入口点指示 uWSGI 如何与应用程序交互。

  • sudo nano main.py

接下来,将以下内容复制并粘贴到文件中。这将导入app从先前创建的应用程序包命名的 Flask 实例

/var/www/TestApp/main.py
from app import app

最后,创建一个requirements.txt文件来指定pip包管理器将安装到 Docker 部署的依赖项

  • sudo nano requirements.txt

添加以下行以将 Flask 添加为依赖项:

/var/www/TestApp/requirements.txt
Flask==1.0.2

这指定要安装的 Flask 版本。在撰写本教程时,1.0.2是最新的 Flask 版本。您可以在Flask的官方网站上查看更新

保存并关闭文件。您已成功设置 Flask 应用程序并准备设置 Docker。

第 2 步 – 设置 Docker

在此步骤中,您将创建两个文件Dockerfilestart.sh,以创建您的 Docker 部署。Dockerfile是包含用于装配图像的命令的文本文档。start.sh文件是一个 shell 脚本,它将构建一个映像并从Dockerfile.

首先,创建Dockerfile.

  • sudo nano Dockerfile

接下来,将所需的配置添加到Dockerfile. 这些命令指定将如何构建映像,以及将包含哪些额外要求。

/var/www/TestApp/Dockerfile
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
RUN apk --update add bash nano
ENV STATIC_URL /static
ENV STATIC_PATH /var/www/app/static
COPY ./requirements.txt /var/www/requirements.txt
RUN pip install -r /var/www/requirements.txt

在此示例中,Docker 映像将基于现有映像构建tiangolo/uwsgi-nginx-flask,您可以在DockerHub 上找到该映像这个特定的 Docker 镜像是比其他镜像更好的选择,因为它支持广泛的 Python 版本和操作系统镜像。

前两行指定您将用于运行应用程序并安装 bash 命令处理器和nano文本编辑器的父映像它还安装了git用于拉取和推送到版本控制托管服务(例如 GitHub、GitLab 和 Bitbucket)客户端。ENV STATIC_URL /static是特定于此 Docker 映像的环境变量。它定义了静态文件夹,所有资产(如图像、CSS 文件和 JavaScript 文件)都来自该文件夹。

最后两行将requirements.txt文件复制到容器中以便执行,然后解析requirements.txt文件以安装指定的依赖项。

添加配置后保存并关闭文件。

随着你Dockerfile的地方,你几乎可以编写start.sh脚本,将打造泊坞窗容器。在编写start.sh脚本之前,首先确保您有一个开放的端口可以在配置中使用。要检查端口是否空闲,请运行以下命令:

  • sudo nc localhost 56733 < /dev/null; echo $?

如果上述命令的输出为1,则端口可用且可用。否则,您将需要选择一个不同的端口以在您的start.sh配置文件中使用。

找到要使用的开放端口后,创建start.sh脚本:

  • sudo nano start.sh

start.sh脚本是一个 shell 脚本,它将Dockerfile从 Docker 镜像构建一个镜像并从生成的 Docker 镜像创建一个容器。将您的配置添加到新文件中:

/var/www/TestApp/start.sh
#!/bin/bash
app="docker.test"
docker build -t ${app} .
docker run -d -p 56733:80 \
  --name=${app} \
  -v $PWD:/app ${app}

第一行称为shebang它指定这是一个 bash 文件并将作为命令执行。下一行指定您要为图像和容器提供的名称,并保存为名为 的变量app下一行指示 Docker 从Dockerfile位于当前目录中的您构建映像这将创建一个docker.test在此示例中调用的图像

最后三行创建了一个名为docker.testport的新容器56733最后,它将当前目录链接到/var/www容器目录。

您可以使用该-d标志以守护程序模式或作为后台进程启动容器。您包括将-p服务器上的端口绑定到 Docker 容器上的特定端口标志。在这种情况下,您将端口绑定5673380Docker 容器上的端口-v标志指定要挂载在容器上的 Docker 卷,在这种情况下,您将整个项目目录挂载到/var/wwwDocker 容器上的文件夹中。

执行start.sh脚本以创建 Docker 镜像并从生成的镜像构建容器:

  • sudo bash start.sh

脚本完成运行后,使用以下命令列出所有正在运行的容器:

  • sudo docker ps

您将收到显示容器的输出:

Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 58b05508f4dd docker.test "/entrypoint.sh /sta…" 12 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:56733->80/tcp docker.test

你会发现docker.test容器正在运行。现在它正在运行,在浏览器中访问指定端口的 IP 地址:http://ip-address:56733

您将看到类似于以下内容的页面:

主页

在此步骤中,您已成功在 Docker 上部署 Flask 应用程序。接下来,您将使用模板向用户显示内容。

第 3 步 — 提供模板文件

模板是向访问您的应用程序的用户显示静态和动态内容的文件。在此步骤中,您将创建一个 HTML 模板来为应用程序创建主页。

首先home.htmlapp/templates目录中创建一个文件

  • sudo nano app/templates/home.html

为您的模板添加代码。此代码将创建一个包含标题和一些文本的 HTML5 页面。

/var/www/TestApp/app/templates/home.html

<!doctype html>

<html lang="en-us">   
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>Welcome home</title>
  </head>

  <body>
    <h1>Home Page</h1>
    <p>This is the home page of our application.</p>
  </body> 
</html>

添加模板后,保存并关闭文件。

接下来,修改app/views.py文件以提供新创建的文件:

  • sudo nano app/views.py

首先,在文件开头添加以下行以render_template从 Flask导入方法。此方法解析 HTML 文件以向用户呈现网页。

/var/www/TestApp/app/views.py
from flask import render_template
...

在文件的末尾,您还将添加一个新路由来渲染模板文件。此代码指定用户home.html在访问/template您的应用程序上路由将获得文件的内容

/var/www/TestApp/app/views.py
...

@app.route('/template')
def template():
    return render_template('home.html')

更新后的app/views.py文件将如下所示:

/var/www/TestApp/app/views.py
from flask import render_template
from app import app 

@app.route('/')
def home():
    return "Hello world!"

@app.route('/template')
def template():
    return render_template('home.html')

完成后保存并关闭文件。

为了使这些更改生效,您需要停止并重新启动 Docker 容器。运行以下命令来重建容器:

  • sudo docker stop docker.test && sudo docker start docker.test

访问您的应用程序以查看正在提供的新模板。http://your-ip-address:56733/template

主页

在此,您已经创建了一个 Docker 模板文件来为您的应用程序的访问者提供服务。在下一步中,您将看到您对应用程序所做的更改如何在无需重新启动 Docker 容器的情况下生效。

第 4 步 – 更新应用程序

有时您需要对应用程序进行更改,无论是安装新需求、更新 Docker 容器,还是更改 HTML 和逻辑。在本节中,您将进行配置touch-reload以进行这些更改,而无需重新启动 Docker 容器。

Python 自动重新加载监视整个文件系统的更改,并在检测到更改时刷新应用程序。在生产中不鼓励自动重新加载,因为它会很快变得资源密集。在此步骤中,您将使用touch-reload监视特定文件的更改并在文件更新或替换时重新加载。

要实现这一点,首先打开你的uwsgi.ini文件:

  • sudo nano uwsgi.ini

接下来,将突出显示的行添加到文件末尾:

/var/www/TestApp/uwsgi.ini
module = main
callable = app
master = true
touch-reload = /app/uwsgi.ini

这指定了将被修改以触发整个应用程序重新加载的文件。完成更改后,保存并关闭文件。

为了证明这一点,请对您的应用程序进行一些小的更改。首先打开您的app/views.py文件:

  • sudo nano app/views.py

替换home函数返回的字符串

/var/www/TestApp/app/views.py
from flask import render_template
from app import app

@app.route('/')
def home():
    return "<b>There has been a change</b>"

@app.route('/template')
def template():
    return render_template('home.html')

进行更改后保存并关闭文件。

接下来,如果您在 处打开应用程序的主页,您会注意到更改没有反映出来。这是因为重新加载的条件是对文件的更改要重新加载应用程序,请使用激活条件:http://ip-address:56733uwsgi.initouch

  • sudo touch uwsgi.ini

再次在浏览器中重新加载应用程序主页。您会发现该应用程序已包含以下更改:

主页更新

在此步骤中,您将设置一个touch-reload条件以在进行更改后更新您的应用程序。

结论

在本教程中,您创建了一个 Flask 应用程序并将其部署到 Docker 容器。您还配置touch-reload为无需重新启动容器即可刷新应用程序。

使用 Docker 上的新应用程序,您现在可以轻松扩展。要了解有关使用 Docker 的更多信息,请查看他们的官方文档

觉得文章有用?

点个广告表达一下你的爱意吧 !😁