作者选择技术教育基金作为Write for DOnations计划的一部分接受捐赠。
介绍
Docker是一个开源应用程序,允许管理员使用容器创建,管理,部署和复制应用程序。 可以将容器视为包含应用程序在操作系统级别运行所需的依赖项的程序包。 这意味着使用Docker部署的每个应用程序都位于自己的环境中,其需求将单独处理。
Flask是一个基于Python构建的Web微框架。 它被称为微框架,因为它不需要特定的工具或插件来运行。 Flask框架轻巧灵活,结构严谨,比其他框架更受欢迎。
使用Docker部署Flask应用程序将允许您以最少的重新配置在不同的服务器上复制应用程序。
在本教程中,您将创建一个Flask应用程序并使用Docker进行部署。 本教程还将介绍如何在部署后更新应用程序。
先决条件
要学习本教程,您需要具备以下条件:
- 具有sudo权限的非root用户,通过使用Ubuntu 18.04指南进行初始服务器设置来配置。
- 一个安装了Docker的Ubuntu 18.04服务器,按照本教程或使用DigitalOcean 一键式Docker镜像进行设置 。
- 按照Ubuntu 18.04教程中如何安装Nginx的第一步安装Nginx 。
第1步 – 设置Flask应用程序
首先,您将创建一个用于存放Flask应用程序的目录结构。 本教程将在/var/www
创建一个名为TestApp
的目录,但您可以根据需要修改命令以命名它。
sudo mkdir /var/www/TestApp
进入新创建的TestApp
目录:
cd /var/www/TestApp
接下来,为Flask应用程序创建基本文件夹结构:
sudo mkdir -p app/static app/templates
-p
标志表示mkdir
将创建一个目录和所有不存在的父目录。 在这种情况下, mkdir
将在创建static
和templates
目录的过程中创建app
父目录。
app
目录将包含与Flask应用程序相关的所有文件,例如其视图和蓝图 。 视图是您为响应对应用程序的请求而编写的代码。 蓝图创建应用程序组件并支持应用程序内或多个应用程序中的常见模式。
static
目录是图像,CSS和JavaScript文件等资源的存在。 您可以在templates
目录中放置项目的HTML模板。
现在基础文件夹结构已完成,请创建运行Flask应用程序所需的文件。 首先,在app
目录中创建一个__init__.py
文件。 该文件告诉Python解释器app
目录是一个包,应该这样对待。
运行以下命令以创建文件:
sudo nano app/__init__.py
Python中的包允许您将模块分组为逻辑命名空间或层次结构。 这种方法使代码可以分解为执行特定功能的单个和可管理的块。
接下来,您将向__init__.py
添加代码,该代码将创建Flask实例并从views.py
文件中导入逻辑,您将在保存此文件后创建该文件。 将以下代码添加到新文件中:
from flask import Flaskapp = Flask(__name__)from app import views
添加该代码后,保存并关闭该文件。
创建了__init__.py
文件后,您就可以在app
目录中创建views.py
文件了。 该文件将包含大部分应用程序逻辑。
sudo nano app/views.py
接下来,将代码添加到views.py
文件中。 这段代码将返回hello world!
访问您网页的用户的字符串:
from app import app@app.route('/')def home(): return "hello world!"
函数上方的@app.route
行称为装饰器 。 装饰器修改后面的函数。 在这种情况下,装饰器告诉Flask哪个URL将触发home()
函数。 home
函数返回的hello world
文本将在浏览器上显示给用户。
使用views.py
文件,您就可以创建uwsgi.ini
文件了。 该文件将包含我们的应用程序的uWSGI配置。 uWSGI是Nginx的部署选项,它既是协议又是应用程序服务器; 应用程序服务器可以提供uWSGI,FastCGI和HTTP协议。
要创建此文件,请运行以下命令:
sudo nano uwsgi.ini
接下来,将以下内容添加到您的文件中以配置uWSGI服务器:
[uwsgi]module = maincallable = appmaster = true
此代码定义将从中提供Flask应用程序的模块。 在这种情况下,这是main.py
文件,在此引用为main
。 callable
选项指示uWSGI使用主应用程序导出的app
实例。 master
选项允许您的应用程序继续运行,因此即使重新加载整个应用程序也几乎没有停机时间。
接下来,创建main.py
文件,该文件是应用程序的入口点。 入口点指示uWSGI如何与应用程序交互。
sudo nano main.py
接下来,将以下内容复制并粘贴到文件中。 这将从先前创建的应用程序包中导入名为app
的Flask实例。
from app import app
最后,创建一个requirements.txt
文件以指定pip
包管理器将为Docker部署安装的依赖项:
sudo nano requirements.txt
添加以下行以将Flask添加为依赖项:
Flask==1.0.2
这指定了要安装的Flask的版本。 在编写本教程时, 1.0.2
是最新的Flask版本。 您可以在Flask的官方网站上查看更新。
保存并关闭文件。 您已成功设置Flask应用程序并准备好设置Docker。
第2步 – 设置Docker
在此步骤中,您将创建两个文件Dockerfile
和start.sh
,以创建Docker部署。 Dockerfile
是一个文本文档,其中包含用于组合图像的命令。 start.sh
文件是一个shell脚本,它将构建一个映像并从Dockerfile
创建一个容器。
首先,创建Dockerfile
。
sudo nano Dockerfile
接下来,将所需的配置添加到Dockerfile
。 这些命令指定如何构建映像,以及将包括哪些额外要求。
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7RUN apk --update add bash nanoENV STATIC_URL /staticENV STATIC_PATH /var/www/app/staticCOPY ./requirements.txt /var/www/requirements.txtRUN 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
后,您几乎已准备好编写将构建Docker容器的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映像创建一个容器。 将配置添加到新文件:
#!/bin/bashapp="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.test
的新容器,该容器在端口56733
处公开。 最后,它将当前目录链接到容器的/var/www
目录。
使用-d
标志以守护进程模式启动容器,或作为后台进程使用。 包含-p
标志以将服务器上的端口绑定到Docker容器上的特定端口。 在这种情况下,您将端口56733
绑定到Docker容器上的端口80
。 -v
标志指定要在容器上安装的Docker卷,在这种情况下,您将整个项目目录挂载到Docker容器上的/var/www
文件夹中。
执行start.sh
脚本以创建Docker镜像并从生成的图像构建容器:
sudo bash start.sh
脚本运行完成后,使用以下命令列出所有正在运行的容器:
sudo docker ps
您将收到显示容器的输出:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES58b05508f4dd 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模板来为应用程序创建主页。
首先在app/templates
目录中创建一个home.html
文件:
sudo nano app/templates/home.html
添加模板的代码。 此代码将创建一个包含标题和一些文本的HTML5页面。
<!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
首先,在文件的开头添加以下行,以从Flask导入render_template
方法。 此方法解析HTML文件以向用户呈现网页。
from flask import render_template...
在文件末尾,您还将添加一个新路由以呈现模板文件。 此代码指定只要用户访问应用程序上的/template
路由,就会向用户提供home.html
文件的内容。
...@app.route('/template')def template(): return render_template('home.html')
更新后的app/views.py
文件如下所示:
from flask import render_templatefrom 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
接下来,将突出显示的行添加到文件的末尾:
module = maincallable = appmaster = truetouch-reload = /app/uwsgi.ini
这指定了一个文件,该文件将被修改以触发整个应用程序重新加载。 完成更改后,保存并关闭文件。
为了证明这一点,请对您的应用程序进行一些小改动。 首先打开你的app/views.py
文件:
sudo nano app/views.py
替换home
函数返回的字符串:
from flask import render_templatefrom 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 : 56733
打开应用程序的主页,您会注意到没有反映更改。 这是因为重新加载的条件是对uwsgi.ini
文件的更改。 要重新加载应用程序,请使用touch
激活条件:
sudo touch uwsgi.ini
再次在浏览器中重新加载应用程序主页。 您会发现该应用程序已包含更改:
在此步骤中,您将设置touch-reload
条件以在进行更改后更新应用程序。
结论
在本教程中,您创建了Flask应用程序并将其部署到Docker容器。 您还配置了touch-reload
以刷新应用程序,而无需重新启动容器。
使用Docker上的新应用程序,您现在可以轻松扩展。 要了解有关使用Docker的更多信息,请查看其官方文档 。