作者选择了(https://www.brightfunds.org/funds/tech-education)作为 写给捐款计划的一部分的捐款。
介绍
Docker是一个开源应用程序,允许管理员使用容器创建,管理,部署和复制应用程序. 容器可以被认为是一个包,其中包含一个应用程序需要在操作系统级别运行的依赖性。
Flask是一个基于 Python构建的网络微框架。它被称为微框架,因为它不需要特定工具或插件来运行。Flask框架是轻量级和灵活的,但结构很强,使其更受欢迎于其他框架。
使用 Docker 部署一个 Flask 应用程序将允许您在不同服务器上复制应用程序,并且需要最少重新配置。
在本教程中,您将创建一个Flask应用程序并与Docker一起部署它。
前提条件
要遵循本教程,您将需要以下内容:
一个非 root 用户使用 sudo 权限,通过遵循 [Ubuntu 18.04 初始服务器设置(LINK0)] 指南进行配置。 * One Ubuntu 18.04 服务器与 Docker 已安装,通过遵循 本教程)或使用 DigitalOcean 单击 Docker 图像进行设置。
步骤 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」母目录。
app
目录将包含与 Flask 应用程序相关的所有文件,如其 views 和 blueprints. Views是你写的代码来响应你的应用程序的请求。
静态
目录是图像,CSS和JavaScript文件等资产活跃的地方,模板
目录是您将为您的项目放置HTML模板的地方。
现在,基础文件夹结构已经完成了,创建运行Flask应用程序所需的文件。 首先,在app
目录中创建一个__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
一旦你添加了该代码,保存并关闭文件。
有了创建的 __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。 装饰者会修改随后的函数. 在这种情况下,装饰者会告诉 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==1.0.2
在写本教程时,‘1.0.2’是最新的Flask版本. 您可以在官方网站上查看 Flask的更新。
保存和关闭文件. 您已成功设置您的 Flask 应用程序,并准备好设置 Docker。
第2步:设置Docker
在此步骤中,您将创建两个文件,即Dockerfile
和start.sh
,以创建您的Docker部署。Dockerfile
是一个文本文档,包含用于组装图像的命令。
首先,创建Dockerfile
。
1sudo nano Dockerfile
接下来,将您想要的配置添加到Dockerfile
。这些命令指定将如何构建图像,以及将包含哪些额外要求。
1[label /var/www/TestApp/Dockerfile]
2FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
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
你会看到一个类似于以下的页面:
在此步骤中,您已经在 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」看到新模板正在服務。
在此,您已创建了一个 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
在您的浏览器中重新加载应用程序首页,您会发现该应用程序已经整合了这些更改:
在此步骤中,您将设置一个触摸重新加载
条件,以在更改后更新您的应用程序。
结论
在本教程中,您创建并部署了一个Flask应用程序到Docker容器中,您还配置了触摸重新加载
,以更新您的应用程序,而无需重新启动容器。
现在,您可以轻松地扩展您的 Docker 应用程序. 有关使用 Docker 的更多信息,请参阅他们的 官方文档。