介绍
Docker是一个开源应用程序,允许管理员使用容器创建,管理,部署和复制应用程序。容器可以看作是一个包,其中包含应用程序在操作系统级别运行所需的依赖项。这意味着使用Docker部署的每个应用程序都生活在其自己的环境中,并且其要求得到单独处理。
Flask是基于Python构建的Web微框架。之所以称为微框架,是因为它不需要特定的工具或插件即可运行。Flask框架轻巧灵活,但结构高度,使其比其他框架更受青睐。
使用Docker部署Flask应用程序将使您能够以最小的重新配置跨不同服务器复制应用程序。
在本教程中,您将创建一个Flask应用程序并将其与Docker一起部署。本教程还将介绍部署后如何更新应用程序。
设置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
将创建一个目录以及所有不存在的父目录。在这种情况下,mkdir
将创建app
在制作的过程中父目录static
和templates
目录。
该app
目录将包含与Flask应用程序相关的所有文件,例如其视图和蓝图。视图是您编写的用于响应对应用程序请求的代码。蓝图创建应用程序组件并支持一个应用程序内或多个应用程序之间的通用模式。
static
目录是资产(例如图像,CSS和JavaScript文件)所在的目录。该templates
目录是放置项目HTML模板的位置。
现在基本文件夹结构已经完成,创建运行Flask应用程序所需的文件。首先,__init__.py
在app
目录内创建一个文件。该文件告诉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。
设置Docker
在此步骤中,您将创建两个文件,Dockerfile
并且start.sh
,以创建泊坞部署。的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版本和OS映像。
前两行指定用于运行应用程序并安装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镜像创建容器。将您的配置添加到新文件:
#/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.test
port 的新容器56733
。最后,它将当前目录链接到/var/www
容器的目录。
您可以使用该-d
标志在守护程序模式下或作为后台进程启动容器。您包括该-p
标志以将服务器上的端口绑定到Docker容器上的特定端口。在这种情况下,您56733
要将端口绑定到80
Docker容器上的端口。该-v
标志指定要在容器上安装的Docker卷,在这种情况下,您要将整个项目目录安装到/var/www
Docker容器上的文件夹。
执行start.sh
脚本以创建Docker映像并根据生成的映像构建容器:
sudo bash start.sh
脚本完成运行后,使用以下命令列出所有正在运行的容器:
sudo docker ps
您将收到显示容器的输出:
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应用程序。接下来,您将使用模板向用户显示内容。
提供模板文件
模板是向访问您的应用程序的用户显示静态和动态内容的文件。在此步骤中,您将创建一个HTML模板来为该应用程序创建一个主页。
首先home.html在app/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容器。
更新应用程序
有时,您需要对应用程序进行更改,无论它是安装新要求,更新Docker容器还是HTML和逻辑更改。在本部分中,您将配置touch-reload
为进行这些更改,而无需重新启动Docker容器。
Python自动重装监视整个文件系统的更改,并在检测到更改时刷新应用程序。不建议在生产中使用自动重装,因为它会很快占用大量资源。在此步骤中,您将touch-reload
用来监视对特定文件的更改并在更新或替换文件时重新加载。
要实现此目的,请先打开uwsgi.ini
文件:
sudo nano uwsgi.ini
接下来,将最后的reload部分添加到文件末尾:
#/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:56733
uwsgi.ini
touch
sudo touch uwsgi.ini
再次在浏览器中重新加载应用程序主页。您会发现该应用程序已合并更改:

在此步骤中,您设置了touch-reload
进行更改后更新应用程序的条件。
结论
在本教程中,您创建了Flask应用程序并将其部署到Docker容器。您还配置touch-reload
为刷新应用程序,而无需重新启动容器。
通过Docker上的新应用程序,您现在可以轻松扩展。要了解有关使用Docker的更多信息,请查看其官方文档。