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

作者选择了 技术教育基金作为 写给捐款计划的一部分接受捐款。

介绍

Docker是一个开源应用程序,允许管理员使用容器创建,管理,部署和复制应用程序。

它被称为微框架,因为它不需要特定工具或插件来运行。

使用 Docker 部署一个 Flask 应用程序将允许您在不同服务器上复制应用程序,并且需要最少重新配置。

在本教程中,您将创建一个Flask应用程序并与Docker一起部署它。

前提条件

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

  • 具有 sudo 权限的非 root 用户通过遵循 [Ubuntu 20.04 初始服务器设置(LINK0)] 指南进行配置。 * 安装了 One Ubuntu 20.04 服务器与 Docker,通过以下 本教程 设置。 * Nginx 通过以下 [如何在 Ubuntu 20.04 上安装 Nginx(LINK3)] 教程的第一步安装。

步骤 1 – 设置Flask应用程序

要开始,你将创建一个目录结构,将保留你的Flask应用程序. 本教程将创建一个名为 TestApp的目录在 /var/www,但你可以修改命令以命名它任何你想要的。

1sudo mkdir /var/www/TestApp

进入新创建的TestApp目录:

1cd /var/www/TestApp

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

1sudo mkdir -p app/static app/templates

「p」旗表示「mkdir」会创建一个目录和所有不存在的母目录,在这种情况下,在创建「静态」和「模板」目录的过程中,「mkdir」会创建「app」母目录。

应用程序目录将包含与Flask应用程序相关的所有文件,如其 viewsblueprints. Views是您写的代码来响应您的应用程序的请求。

静态目录是图像,CSS和JavaScript文件等资产活跃的地方,模板目录是您将为您的项目放置HTML模板的地方。

现在基础文件夹结构已经完成,您需要创建运行Flask应用程序所需的文件。 首先,使用Nano或您选择的文本编辑器在应用程序目录中创建一个__init__.py文件。

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

1sudo nano app/__init__.py

Python 中的包允许您将模块组成逻辑名称空间或等级,这种方法允许将代码分解为执行特定功能的单个和可管理的块。

接下来,您将添加代码到 __init__.py,这将创建一个 Flask 实例,并从 views.py 文件中导入逻辑,您将创建该文件保存后。

1[label /var/www/TestApp/app/__init__.py]
2from flask import Flask
3app = Flask(__name__)
4from app import views

一旦你添加了该代码,保存并关闭文件. 您可以保存和关闭文件,按Ctrl+X,然后在提示时,YEnter

有了创建的 __init__.py 文件,你已经准备好在你的 app 目录中创建 views.py 文件。

1sudo nano app/views.py

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

1[label /var/www/TestApp/app/views.py]
2from app import app
3
4@app.route('/')
5def home():
6   return "hello world!"

函数上方的 @app.route 行称为 decorator。 Decorators 是 Flask 广泛使用的 Python 语言公约,其目的是立即修改函数,在这种情况下,decorator 会告诉 Flask 哪个 URL 会触发 home() 函数。

有了「views.py」文件,您已经准备好创建「uwsgi.ini」文件. 此文件将包含我们应用程序的 uWSGI配置。 uWSGI 是 Nginx 的部署选项,既是一个协议,也是一个应用程序服务器;应用程序服务器可以为 uWSGI、FastCGI 和 HTTP 协议提供服务。

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

1sudo nano uwsgi.ini

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

1[label /var/www/TestApp/uwsgi.ini]
2[uwsgi]
3module = main
4callable = app
5master = true

此代码定义了Flask应用程序将由哪个模块提供服务。在这种情况下,这是main.py文件,这里称为main可调用选项指示uWSGI使用由主应用程序导出的app实例。

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

1sudo nano main.py

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

1[label /var/www/TestApp/main.py]
2from app import app

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

1sudo nano requirements.txt

添加以下行以添加 Flask 作为依赖:

1[label /var/www/TestApp/requirements.txt]
2Flask>=2.0.2

在写本教程时,2.0.2是最新的Flask版本,并且指定>=2.0.2将确保您获得版本 2.0.2 或更高版本. 因为您正在制作本教程中的基本测试应用程序,语法不太可能因Flask的未来更新而过时,但如果您想保持安全并仍然收到较小的更新,您可以通过指定Flask>2.0.2,<3.0等内容来指定您不想安装未来的主要版本。

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

第2步:设置Docker

在此步骤中,您将创建两个文件,即Dockerfilestart.sh,以创建您的Docker部署。Dockerfile是一个文本文档,包含用于组装图像的命令。

首先,创建Dockerfile

1sudo nano Dockerfile

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

1[label /var/www/TestApp/Dockerfile]
2FROM tiangolo/uwsgi-nginx-flask:python3.8-alpine
3RUN apk --update add bash nano
4ENV STATIC_URL /static
5ENV STATIC_PATH /var/www/app/static
6COPY ./requirements.txt /var/www/requirements.txt
7RUN pip install -r /var/www/requirements.txt

在本示例中,Docker 图像将建立在现有图像中,‘tiangolo/uwsgi-nginx-flask’,您可以在 DockerHub找到它。

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

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

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

有了你的Dockerfile,你几乎准备好写你的start.sh脚本,它将构建 Docker 容器。在写start.sh脚本之前,先确保你在配置中有一个开放的端口。

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

如果上面的命令的输出是1,那么端口是免费的和可用。否则,你需要选择一个不同的端口用于你的start.sh配置文件。

一旦你找到一个开放的端口来使用,创建start.sh脚本:

1sudo nano start.sh

start.sh脚本是一个壳脚本,它将从Dockerfile构建一个图像,并从结果的Docker图像创建一个容器。

1[label /var/www/TestApp/start.sh]
2#!/bin/bash
3app="docker.test"
4docker build -t ${app} .
5docker run -d -p 56733:80 \
6  --name=${app} \
7  -v $PWD:/app ${app}

第一个行称为 shebang. 它指明这是一个 bash 文件,并将作为命令执行。 下一个行指明您要给图像和容器的名称,并将其保存为名为app的变量。

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

您使用d旗启动集装箱在daemon模式下,或作为背景流程。 您添加p旗将服务器上的端口绑定到 Docker 集装箱上的特定端口。 在这种情况下,您将端口56733绑定到 Docker 集装箱上的端口80

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

运行start.sh脚本来创建 Docker 图像并从结果图像中构建一个容器:

1sudo bash start.sh

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

1sudo docker ps

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

1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
358b05508f4dd 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

你会看到一个类似于以下的页面:

the home page

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

步骤 3 – 服务 Template 文件

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

app/templates目录中创建一个home.html文件:

1sudo nano app/templates/home.html

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

 1[label /var/www/TestApp/app/templates/home.html]
 2
 3<!doctype html>
 4
 5<html lang="en-us">   
 6  <head>
 7    <meta charset="utf-8">
 8    <meta http-equiv="x-ua-compatible" content="ie=edge">
 9    <title>Welcome home</title>
10  </head>
11
12  <body>
13    <h1>Home Page</h1>
14    <p>This is the home page of our application.</p>
15  </body> 
16</html>

保存并关闭文件,一旦您添加了模板。

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

1sudo nano app/views.py

首先,在文件开始时添加以下行以从 Flask 导入 render_template 方法。

1[label /var/www/TestApp/app/views.py]
2from flask import render_template
3...

在文件的末尾,您还会添加一个新的路径来渲染模板文件. 此代码规定用户每次访问您的应用程序中的/template路径时都会收到home.html文件的内容。

1[label /var/www/TestApp/app/views.py]
2...
3
4@app.route('/template')
5def template():
6    return render_template('home.html')

更新后的app/views.py文件将看起来像这样:

 1[label /var/www/TestApp/app/views.py]
 2from flask import render_template
 3from app import app 
 4
 5@app.route('/')
 6def home():
 7    return "Hello world!"
 8
 9@app.route('/template')
10def template():
11    return render_template('home.html')

完成后保存并关闭文件。

要使这些更改生效,您需要停止并重新启动 Docker 容器。

1sudo docker stop docker.test && sudo docker start docker.test

請訪問您的應用程式在「http://your-ip-address:56733/template」看到新模板正在服務。

homepage

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

步骤4:更新应用程序

有时您需要对应用程序进行更改,无论是安装新要求、更新 Docker 容器还是 HTML 和逻辑变化。

Python autoreloading 监控整个文件系统的变化,并在检测到变化时更新应用程序。 Autoreloading 被阻止在生产中,因为它可以非常快地变得资源密集。

要实现这一点,请通过打开您的uwsgi.ini文件开始:

1sudo nano uwsgi.ini

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

1[label /var/www/TestApp/uwsgi.ini]
2module = main
3callable = app
4master = true
5touch-reload = /app/uwsgi.ini

这指定了一个文件,将被更改,以触发整个应用程序重新加载.一旦你做了更改,保存和关闭文件。

要证明这一点,请对您的应用程序做一个小小的更改,首先打开您的app/views.py文件:

1sudo nano app/views.py

将返回的字符串替换为Home函数:

 1[label  /var/www/TestApp/app/views.py]
 2from flask import render_template
 3from app import app
 4
 5@app.route('/')
 6def home():
 7    return "<b>There has been a change</b>"
 8
 9@app.route('/template')
10def template():
11    return render_template('home.html')

保存并关闭文件后,你做了更改。

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

1sudo touch uwsgi.ini

在您的浏览器中重新加载应用程序首页,您会发现该应用程序已经整合了这些更改:

Homepage Updated

在此步骤中,您将设置一个触摸重新加载条件,以在更改后更新您的应用程序。

结论

在本教程中,您创建并部署了一个Flask应用程序到Docker容器中,您还配置了触摸重新加载,以更新您的应用程序,而无需重新启动容器。

现在,您可以轻松地扩展您的 Docker 应用程序. 有关使用 Docker 的更多信息,请参阅他们的 官方文档

Published At
Categories with 技术
comments powered by Disqus