作者选择了 Internet Archive作为 Write for Donations计划的一部分接受捐赠。
介绍
在构建和维护多种不同的技术时,开发 Web 应用程序可能会变得复杂和耗时。考虑更轻的重量选项,旨在减少您的应用程序的复杂性和生产时间,可以带来更灵活和可扩展的解决方案。作为一个基于 Python构建的微型 Web 框架, Flask为开发人员提供一种可扩展的方式来通过可以集成到项目中的扩展来发展他们的应用程序。
Docker Compose进一步简化了开发环境,允许您在单个文件中定义您的基础设施,包括您的应用程序服务,网络卷和绑定堆栈。使用Docker Compose在运行多个docker container run
命令时提供易用性。它允许您在单个Compose文件中定义您的所有服务,并使用单个命令创建和启动您的配置中的所有服务。
在本教程中,您将构建、包装和运行您要做的 Web 应用程序,使用 Flask、 Nginx 和 MongoDB 在 Docker containers中。您将定义整个堆栈配置在一个 docker-compose.yml
文件中,以及 Python、MongoDB 和 Nginx 的配置文件。 Flask 需要一个 Web 服务器来服务 HTTP 请求,因此您还将使用 Gunicorn,这是一个 Python WSGI HTTP 服务器,来服务应用程序。
前提条件
要遵循本教程,您将需要以下内容:
- 具有
sudo
权限的非根用户,通过遵循 初始服务器设置教程中的步骤进行配置。 - Docker 与 How To Install and Use Docker步骤 1 和步骤 2 的指示一起安装。
步骤 1 — 在 Docker Compose 中编写堆栈配置
通过在 Docker 上构建应用程序,您可以轻松地根据您在 Docker Compose 中所做的配置更改来编辑版本基础设施。 基础设施可以被定义为单个文件并用单个命令构建。
docker-compose.yml
文件允许您将您的应用基础设施定义为单独的服务. 服务可以相互连接,每个服务可以附加一个 volume 用于持续存储. 卷存储在由 Docker 管理的主机文件系统的一部分(/var/lib/docker/volumes/
在 Linux 上)。
卷是在 Docker 中保持数据的最佳方法,因为卷中的数据可以导出或与其他应用程序共享,如需有关在 Docker 中共享数据的更多信息,请参阅 如何在 Docker 容器和主机之间共享数据。
要开始,请在您的服务器上的主目录中创建应用程序的目录:
1mkdir flaskapp
移动到新创建的目录:
1cd flaskapp
然后创建docker-compose.yml
文件:
1nano docker-compose.yml
「docker-compose.yml」檔案以識別 Docker Compose 檔案版本的版本號碼開始。Docker Compose 檔案版本「3」針對 Docker Engine 版本「1.13.0+」的目標,這是此設定的前提。
1[label docker-compose.yml]
2version: '3'
3services:
现在,您将将flask
定义为您的docker-compose.yml
文件中的第一个服务. 添加以下代码来定义 Flask 服务:
1[label docker-compose.yml]
2. . .
3 flask:
4 build:
5 context: app
6 dockerfile: Dockerfile
7 container_name: flask
8 image: digitalocean.com/flask-python:3.6
9 restart: unless-stopped
10 environment:
11 APP_ENV: "prod"
12 APP_DEBUG: "False"
13 APP_PORT: 5000
14 MONGODB_DATABASE: flaskdb
15 MONGODB_USERNAME: flaskuser
16 MONGODB_PASSWORD: your_mongodb_password
17 MONGODB_HOSTNAME: mongodb
18 volumes:
19 - appdata:/var/www
20 depends_on:
21 - mongodb
22 networks:
23 - frontend
24 - backend
构建
属性定义了构建的背景
,在这种情况下,将包含Dockerfile
的应用
文件夹。
您使用container_name
属性来定义每个容器的名称。图像
属性指定图像的名称以及 Docker 图像将被标记为什么。重新启动
属性定义了容器应该如何重新启动 – 在您的情况下,它是除非停止
的。
环境
属性包含传送到容器的环境变量。您需要为环境变量MONGODB_PASSWORD
提供安全密码。 volumes
属性定义了所使用的服务的卷数。在您的情况下,appdata
的卷在容器内安装在/var/www
目录中。depends_on
属性定义了Flask所依赖的服务,以便其正常工作。在这种情况下,flask
服务将依赖mongodb
,因为mongodb
服务作为您的应用程序的数据库。depends_on
确保flask
服务只在mongodb
服务运行时运行。
该网络
属性指定前端
和后端
为flask
服务将可以访问的网络。
随着flask
服务的定义,您已经准备好将 MongoDB 配置添加到文件中。在本示例中,您将使用官方的4.0.8
版本的mongo
图像。在flask service
之后,将以下代码添加到您的docker-compose.yml
文件中:
1[label docker-compose.yml]
2. . .
3 mongodb:
4 image: mongo:4.0.8
5 container_name: mongodb
6 restart: unless-stopped
7 command: mongod --auth
8 environment:
9 MONGO_INITDB_ROOT_USERNAME: mongodbuser
10 MONGO_INITDB_ROOT_PASSWORD: your_mongodb_root_password
11 MONGO_INITDB_DATABASE: flaskdb
12 MONGODB_DATA_DIR: /data/db
13 MONDODB_LOG_DIR: /dev/null
14 volumes:
15 - mongodbdata:/data/db
16 networks:
17 - backend
此服务的container_name
为mongodb
,其重新启动策略为unless-stopped
。您使用命令
属性来定义在启动容器时将执行的命令。
环境变量 MONGO_INITDB_ROOT_USERNAME
和 MONGO_INITDB_ROOT_PASSWORD
会创建一个根用户,使用给定的凭据,所以请确保用强大的密码替换位置持有人。
默认情况下,MongoDB 将其数据存储在 /data/db
中,因此在 /data/db
文件夹中的数据将被写入命名卷 mongodbdata
以保持持续性。 因此,在重新启动的情况下,您将不会丢失数据库。
接下来,您将为您的应用程序定义 Web 服务器. 将以下代码添加到您的 docker-compose.yml
文件中,以配置 Nginx:
1[label docker-compose.yml]
2. . .
3 webserver:
4 build:
5 context: nginx
6 dockerfile: Dockerfile
7 image: digitalocean.com/webserver:latest
8 container_name: webserver
9 restart: unless-stopped
10 environment:
11 APP_ENV: "prod"
12 APP_NAME: "webserver"
13 APP_DEBUG: "false"
14 SERVICE_NAME: "webserver"
15 ports:
16 - "80:80"
17 - "443:443"
18 volumes:
19 - nginxdata:/var/log/nginx
20 depends_on:
21 - flask
22 networks:
23 - frontend
在这里,您已经定义了构建
的背景
,即包含Dockerfile
的nginx
文件夹。使用图像
属性,您指定了用于标记和运行容器的图像。端口
属性将配置 Nginx 服务以通过:80
和:443
进行公开访问,而卷
将nginxdata
的卷插入容器中的/var/log/nginx
目录。
您已将 Web 服务器服务depends_on
为flask
的服务定义,最后网络
属性定义了网络的 Web 服务器服务将访问前端
。
接下来,您将创建 bridge networks 以允许容器相互通信。
1[label docker-compose.yml]
2. . .
3networks:
4 frontend:
5 driver: bridge
6 backend:
7 driver: bridge
您定义了两个网络――前端
和后端
――服务要连接到。前端服务,如 Nginx,将连接到前端
网络,因为它需要公开访问。
接下来,您将使用卷来保存数据库、应用程序和配置文件. 由于您的应用程序将使用数据库和文件,因此必须坚持对它们进行的更改。 卷由 Docker 管理并存储在文件系统中。
1[label docker-compose.yml]
2. . .
3volumes:
4 mongodbdata:
5 driver: local
6 appdata:
7 driver: local
8 nginxdata:
9 driver: local
在这里,您已经定义了mongodbdata
,appdata
和nginxdata
为您的MongoDB数据库,Flask应用数据和Nginx网页服务器日志的持续使用的卷。所有这些卷都使用本地
驱动程序来本地存储数据。这些卷被用来保持这些数据,以便在重新启动容器后丢失数据,如您的MongoDB数据库和Nginx网页服务器日志。
您的完整的 'docker-compose.yml' 文件将看起来如下:
1[label docker-compose.yml]
2version: '3'
3services:
4
5 flask:
6 build:
7 context: app
8 dockerfile: Dockerfile
9 container_name: flask
10 image: digitalocean.com/flask-python:3.6
11 restart: unless-stopped
12 environment:
13 APP_ENV: "prod"
14 APP_DEBUG: "False"
15 APP_PORT: 5000
16 MONGODB_DATABASE: flaskdb
17 MONGODB_USERNAME: flaskuser
18 MONGODB_PASSWORD: your_mongodb_password
19 MONGODB_HOSTNAME: mongodb
20 volumes:
21 - appdata:/var/www
22 depends_on:
23 - mongodb
24 networks:
25 - frontend
26 - backend
27
28 mongodb:
29 image: mongo:4.0.8
30 container_name: mongodb
31 restart: unless-stopped
32 command: mongod --auth
33 environment:
34 MONGO_INITDB_ROOT_USERNAME: mongodbuser
35 MONGO_INITDB_ROOT_PASSWORD: your_mongodb_root_password
36 MONGO_INITDB_DATABASE: flaskdb
37 MONGODB_DATA_DIR: /data/db
38 MONDODB_LOG_DIR: /dev/null
39 volumes:
40 - mongodbdata:/data/db
41 networks:
42 - backend
43
44 webserver:
45 build:
46 context: nginx
47 dockerfile: Dockerfile
48 image: digitalocean.com/webserver:latest
49 container_name: webserver
50 restart: unless-stopped
51 environment:
52 APP_ENV: "prod"
53 APP_NAME: "webserver"
54 APP_DEBUG: "true"
55 SERVICE_NAME: "webserver"
56 ports:
57 - "80:80"
58 - "443:443"
59 volumes:
60 - nginxdata:/var/log/nginx
61 depends_on:
62 - flask
63 networks:
64 - frontend
65
66networks:
67 frontend:
68 driver: bridge
69 backend:
70 driver: bridge
71
72volumes:
73 mongodbdata:
74 driver: local
75 appdata:
76 driver: local
77 nginxdata:
78 driver: local
保存文件并在验证配置后离开编辑器。
您已经在docker-compose.yml
文件中定义了整个应用程序堆栈的 Docker 配置,您现在将继续为 Flask 和 Web 服务器编写 Dockerfiles。
步骤 2 — 撰写 Flask 和 Web 服务器 Docker 文件
借助 Docker,您可以从名为 Dockerfile 的文件中构建容器来运行您的应用程序. Dockerfile 是一个工具,允许您创建自定义图像,您可以使用它来安装应用程序所需的软件,并根据您的要求配置您的容器。
在此步骤中,您将为 Flask 和 Web 服务器编写 Dockerfiles. 要开始,请为您的 Flask 应用程序创建应用程序
目录:
1mkdir app
接下来,在app
目录中创建您的Flask应用程序的Dockerfile
:
1nano app/Dockerfile
将以下代码添加到文件中以定制您的 Flask 容器:
1[label app/Dockerfile]
2FROM python:3.6.8-alpine3.9
3
4LABEL MAINTAINER="FirstName LastName <[email protected]>"
5
6ENV GROUP_ID=1000 \
7 USER_ID=1000
8
9WORKDIR /var/www/
在这个Dockerfile
中,您正在创建一个基于 Alpine 3.9 预安装 Python 3.6.8 的图像(3.6.8-alpine3.9
图像)的顶部。
「ENV」指令被用来定义我们群组和用户ID的环境变量。 Linux Standard Base (LSB)规定, UIDs 和 GIDs 0-99是系统静态分配的。 UIDs 100-999是系统用户和群组动态分配的。 UIDs 1000-59999是用户帐户的动态分配的。
WORKDIR
指令定义了容器的工作目录,请确保用您的姓名和电子邮件地址代替LABEL MAINTAINER
字段。
添加以下代码块,将 Flask 应用程序复制到容器中并安装必要的依赖:
1[label app/Dockerfile]
2. . .
3ADD ./requirements.txt /var/www/requirements.txt
4RUN pip install -r requirements.txt
5ADD . /var/www/
6RUN pip install gunicorn
下面的代码将使用ADD
指令将文件从本地app
目录复制到容器上的/var/www
目录。接下来,Dockerfile将使用RUN
指令来安装Gunicorn和在requirements.txt
文件中指定的包,您将在教程中稍后创建。
以下代码块添加了一个新的用户和组,并初始化应用程序:
1[label app/Dockerfile]
2. . .
3RUN addgroup -g $GROUP_ID www
4RUN adduser -D -u $USER_ID -G www www -s /bin/sh
5
6USER www
7
8EXPOSE 5000
9
10CMD [ "gunicorn", "-w", "4", "--bind", "0.0.0.0:5000", "wsgi"]
默认情况下,Docker 容器将作为 root 用户运行。 root 用户可以访问系统中的所有内容,因此安全漏洞的后果可能是灾难性的。
此代码将首先使用addgroup
命令创建一个名为www
的新组。
adduser -D -u $USER_ID -G www -s /bin/sh
线将创建一个具有ENV
变量定义的www
用户ID的www
字符串。-s
旗将创建用户的主目录,如果它不存在,并将默认登录壳设置为/bin/sh
。
用户
命令定义了在容器中运行的程序将使用www
用户。Gunicorn会听到:5000
,所以你会用EXPOSE
命令打开这个端口。
最后,CMD [gunicorn
,-w
,4
,--bind
,0.0.0.0:5000
,wsgi
]行运行命令以启动Gunicorn服务器,四名员工在端口
5000`上听。
完成的Dockerfile
将看起来如下:
1[label app/Dockerfile]
2FROM python:3.6.8-alpine3.9
3
4LABEL MAINTAINER="FirstName LastName <[email protected]>"
5
6ENV GROUP_ID=1000 \
7 USER_ID=1000
8
9WORKDIR /var/www/
10
11ADD . /var/www/
12RUN pip install -r requirements.txt
13RUN pip install gunicorn
14
15RUN addgroup -g $GROUP_ID www
16RUN adduser -D -u $USER_ID -G www www -s /bin/sh
17
18USER www
19
20EXPOSE 5000
21
22CMD [ "gunicorn", "-w", "4", "--bind", "0.0.0.0:5000", "wsgi"]
保存文件并离开文本编辑器。
接下来,创建一个新的目录,以保持您的 Nginx 配置:
1mkdir nginx
然后在nginx
目录中为您的 Nginx Web 服务器创建Dockerfile
:
1nano nginx/Dockerfile
将以下代码添加到文件中,以创建为您的 Nginx 容器构建图像的 Dockerfile:
1[label nginx/Dockerfile]
2FROM alpine:latest
3
4LABEL MAINTAINER="FirstName LastName <[email protected]>"
5
6RUN apk --update add nginx && \
7 ln -sf /dev/stdout /var/log/nginx/access.log && \
8 ln -sf /dev/stderr /var/log/nginx/error.log && \
9 mkdir /etc/nginx/sites-enabled/ && \
10 mkdir -p /run/nginx && \
11 rm -rf /etc/nginx/conf.d/default.conf && \
12 rm -rf /var/cache/apk/*
13
14COPY conf.d/app.conf /etc/nginx/conf.d/app.conf
15
16EXPOSE 80 443
17CMD ["nginx", "-g", "daemon off;"]
这个 Nginx Dockerfile
使用一个 alpine
基础图像,这是一个微小的 Linux 发行版,为安全而构建的攻击表面很小。
在RUN
指令中,您正在安装nginx
以及创建符号链接来发布错误和访问日志到标准错误(/dev/stderr)和输出(
/dev/stdout))。将错误发布到标准错误和输出是最好的做法,因为容器是短暂的,这样做日志被发送到Docker日志,从那里您可以将日志发送到一个日志服务,如弹性堆栈,以保持持久性。完成后,执行命令来删除default.conf
和/var/cache/apk/*
,以减少结果图像的大小。在一个单一的RUN
中执行所有这些命令,减少了图像中的层次数,这也减少了结果图像的大小。
COPY
指令复制了容器内部的app.conf
Web 服务器配置,EXPOSE
指令确保容器在端口:80
和:443
上收听,因为您的应用程序将在:80
上运行,安全端口为:443
。
最后,CMD
指令定义了启动 Nginx 服务器的命令。
保存文件并离开文本编辑器。
现在Dockerfile
已经准备好了,您已经准备好配置 Nginx 反向代理来将流量路由到 Flask 应用程序。
步骤 3 – 配置 Nginx 反向代理
在此步骤中,您将将 Nginx 配置为反向代理,以便在 `:5000 上向 Gunicorn 传输请求。 使用反向代理服务器将客户端请求直接发送到相应的后端服务器。
开始创建nginx/conf.d
目录:
1mkdir nginx/conf.d
要配置 Nginx,您需要在nginx/conf.d/
文件夹中创建一个app.conf
文件,该文件包含反向代理需要向 Gunicorn 传递请求的配置。
1nano nginx/conf.d/app.conf
将以下内容放入 app.conf 文件中:
1[label nginx/conf.d/app.conf]
2upstream app_server {
3 server flask:5000;
4}
5
6server {
7 listen 80;
8 server_name _;
9 error_log /var/log/nginx/error.log;
10 access_log /var/log/nginx/access.log;
11 client_max_body_size 64M;
12
13 location / {
14 try_files $uri @proxy_to_app;
15 }
16
17 location @proxy_to_app {
18 gzip_static on;
19
20 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
21 proxy_set_header X-Forwarded-Proto $scheme;
22 proxy_set_header Host $http_host;
23 proxy_buffering off;
24 proxy_redirect off;
25 proxy_pass http://app_server;
26 }
27}
这将首先定义上游服务器(http://nginx.org/en/docs/http/ngx_http_upstream_module.html),通常用于指定用于路由或负载平衡的 Web 或应用程序服务器。
您的上游服务器,app_server,用服务器
指令定义服务器地址,该指令被标识为容器名称flask:5000。
Nginx Web 服务器的配置是在服务器
块中定义的。倾听
指令定义了您的服务器会听取接入请求的端口号。error_log
和access_log
指令定义了写日志的文件。proxy_pass
指令用于设置上游服务器将请求转发到http://app_server
。
保存并关闭文件。
随着 Nginx Web 服务器的配置,您可以继续创建 Flask to-do API。
步骤 4 – 创建 Flask To-do API
现在你已经构建了你的环境,你已经准备好构建你的应用程序. 在这个步骤中,你将写一个要做 API 应用程序,将保存和显示从 POST 请求发送的要做笔记。
通过在应用程序
目录中创建requirements.txt
文件开始:
1nano app/requirements.txt
此文件用于为您的应用程序安装依赖性。本教程的实施将使用 Flask
, Flask-PyMongo
和 requests
. 将以下内容添加到 requirements.txt
文件:
1[label app/requirements.txt]
2Flask==1.0.2
3Flask-PyMongo==2.2.0
4requests==2.20.1
保存文件并在输入要求后离开编辑器。
接下来,创建app.py
文件以在app
目录中包含Flask应用程序代码:
1nano app/app.py
在你的新的app.py
文件中,输入代码来导入依赖:
1[label app/app.py]
2import os
3from flask import Flask, request, jsonify
4from flask_pymongo import PyMongo
从flask
库中导入了Flask
,request
和jsonify
对象来实时化应用程序,处理请求,并分别发送 JSON 响应。
接下来,添加连接到 MongoDB 所需的代码:
1[label app/app.py]
2. . .
3application = Flask(__name__)
4
5application.config["MONGO_URI"] = 'mongodb://' + os.environ['MONGODB_USERNAME'] + ':' + os.environ['MONGODB_PASSWORD'] + '@' + os.environ['MONGODB_HOSTNAME'] + ':27017/' + os.environ['MONGODB_DATABASE']
6
7mongo = PyMongo(application)
8db = mongo.db
Flask(__name__)
将应用程序对象加载到应用程序
变量中。接下来,代码将 MongoDB 连接字符串从使用os.environ
的环境变量中构建出来。
现在您将添加代码来创建索引消息:
1[label app/app.py]
2. . .
3@application.route('/')
4def index():
5 return jsonify(
6 status=True,
7 message='Welcome to the Dockerized Flask MongoDB app!'
8 )
@application.route('/')
定义了 API 的 /
GET 路径,在这里,您的 index()
函数使用 `jsonify' 方法返回 JSON 字符串。
接下来,添加/todo
路径列出所有任务:
1[label app/app.py]
2. . .
3@application.route('/todo')
4def todo():
5 _todos = db.todo.find()
6
7 item = {}
8 data = []
9 for todo in _todos:
10 item = {
11 'id': str(todo['_id']),
12 'todo': todo['todo']
13 }
14 data.append(item)
15
16 return jsonify(
17 status=True,
18 data=data
19 )
@application.route('/todo')
定义了 API 的/todo
GET 路径,该路径返回了数据库中的to-dos
。db.todo.find()
方法返回了数据库中的所有to-dos
。接下来,您重复了_todos
来构建一个项目
,其中仅包含将它们附加到data
数组的对象中的id
和todo
,并最终返回为 JSON。
接下来,添加创建任务的代码:
1[label app/app.py]
2. . .
3@application.route('/todo', methods=['POST'])
4def createTodo():
5 data = request.get_json(force=True)
6 item = {
7 'todo': data['todo']
8 }
9 db.todo.insert_one(item)
10
11 return jsonify(
12 status=True,
13 message='To-do saved successfully!'
14 ), 201
@application.route('/todo')
定义了 API 的/todo
POST 路径,该路径在数据库中创建了一个任务注释。request.get_json(force=True)
得到你发布到路径的 JSON,而item
被用来构建将被保存在任务中的 JSON。db.todo.insert_one(item)
被用来将一个项目插入数据库。
现在你添加代码来运行应用程序:
1[label app/app.py]
2. . .
3if __name__ == "__main__":
4 ENVIRONMENT_DEBUG = os.environ.get("APP_DEBUG", True)
5 ENVIRONMENT_PORT = os.environ.get("APP_PORT", 5000)
6 application.run(host='0.0.0.0', port=ENVIRONMENT_PORT, debug=ENVIRONMENT_DEBUG)
条件 __name__ == '__main__' 用于检查是否全球变量,
name,在模块中是您的程序的入口点,是
"main",然后运行应用程序. 如果 __name__
等于 "__main__",那么在
if块内的代码将使用这个命令执行应用程序
application.run(host='0.0.0.0', port=ENVIRONMENT_PORT, debug=ENVIRONMENT_DEBUG)`。
接下来,我们从使用os.environ.get()
的环境变量中获取ENVIRONMENT_DEBUG
和ENVIRONMENT_PORT
的值,使用键作为第一个参数和默认值作为第二个参数。
完成的「app.py」檔案將看起來像這樣:
1[label app/app.py]
2import os
3from flask import Flask, request, jsonify
4from flask_pymongo import PyMongo
5
6application = Flask(__name__)
7
8application.config["MONGO_URI"] = 'mongodb://' + os.environ['MONGODB_USERNAME'] + ':' + os.environ['MONGODB_PASSWORD'] + '@' + os.environ['MONGODB_HOSTNAME'] + ':27017/' + os.environ['MONGODB_DATABASE']
9
10mongo = PyMongo(application)
11db = mongo.db
12
13@application.route('/')
14def index():
15 return jsonify(
16 status=True,
17 message='Welcome to the Dockerized Flask MongoDB app!'
18 )
19
20@application.route('/todo')
21def todo():
22 _todos = db.todo.find()
23
24 item = {}
25 data = []
26 for todo in _todos:
27 item = {
28 'id': str(todo['_id']),
29 'todo': todo['todo']
30 }
31 data.append(item)
32
33 return jsonify(
34 status=True,
35 data=data
36 )
37
38@application.route('/todo', methods=['POST'])
39def createTodo():
40 data = request.get_json(force=True)
41 item = {
42 'todo': data['todo']
43 }
44 db.todo.insert_one(item)
45
46 return jsonify(
47 status=True,
48 message='To-do saved successfully!'
49 ), 201
50
51if __name__ == "__main__":
52 ENVIRONMENT_DEBUG = os.environ.get("APP_DEBUG", True)
53 ENVIRONMENT_PORT = os.environ.get("APP_PORT", 5000)
54 application.run(host='0.0.0.0', port=ENVIRONMENT_PORT, debug=ENVIRONMENT_DEBUG)
保存文件并离开编辑器。
接下来,在app
目录中创建wsgi.py
文件。
1nano app/wsgi.py
wsgi.py
文件会创建一个应用程序对象(或可调用)以便服务器可以使用它. 每次收到请求时,服务器会使用该应用程序对象在解析 URL 时运行应用程序的请求处理器。
將下列內容放入「wsgi.py」檔案中,保存檔案,然後退出文本編輯器:
1[label app/wsgi.py]
2from app import application
3
4if __name__ == "__main__":
5 application.run()
此wsgi.py
文件从app.py
文件中导入应用程序对象,并为 Gunicorn 服务器创建应用程序对象。
To-do 应用程序现在已经在位,所以您已经准备好开始在容器中运行应用程序。
步骤5:构建和运行集装箱
现在,你已经定义了你的docker-compose.yml
文件中的所有服务及其配置,你可以开始容器。
由于服务被定义为单个文件,您需要发出单个命令来启动容器,创建卷,并设置网络. 该命令还为您的 Flask 应用程序和 Nginx 网络服务器构建图像。
1docker-compose up -d
第一次运行该命令时,它会下载所有必要的Docker图像,这可能需要一段时间。一旦这些图像下载并存储在您的本地机器上,‘docker-compose’将创建您的容器。
使用以下命令列出运行容器,一旦构建过程完成:
1docker ps
您将看到类似于以下的输出:
1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f20e9a7fd2b9 digitalocean.com/webserver:latest "nginx -g 'daemon of…" 2 weeks ago Up 2 weeks 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp webserver
43d53ea054517 digitalocean.com/flask-python:3.6 "gunicorn -w 4 --bin…" 2 weeks ago Up 2 weeks 5000/tcp flask
596f5a91fc0db mongo:4.0.8 "docker-entrypoint.s…" 2 weeks ago Up 2 weeks 27017/tcp mongodb
CONTAINER ID
是一个用于访问集装箱的唯一标识符。IMAGE
定义了给定集装箱的图像名称。NAMES
字段是创建集装箱的服务名称,类似于CONTAINER ID
,它们可以用于访问集装箱。最后,STATUS
提供了有关集装箱运行、重新启动或停止状态的信息。
您已经使用了docker-compose
命令来从配置文件中构建您的容器. 在下一步,您将为您的应用程序创建一个MongoDB用户。
步骤 6 — 创建您的 MongoDB 数据库的用户
默认情况下,MongoDB允许用户无需身份验证登录,并授予无限权限. 在此步骤中,您将通过创建一个专用用户来保护您的MongoDB数据库。
要做到这一点,您需要在docker-compose.yml
文件环境变量MONGO_INITDB_ROOT_USERNAME
和MONGO_INITDB_ROOT_PASSWORD
中为mongodb
服务设置的 root 用户名和密码。一般来说,在与数据库互动时最好避免使用 root 管理帐户。相反,您将为您的 Flask 应用程序创建一个专用数据库用户,以及一个新的数据库,Flask 应用程序将被允许访问。
要创建一个新的用户,首先在mongodb
容器上启动一个交互式壳:
1docker exec -it mongodb bash
您可以使用docker exec
命令在运行容器内运行命令,并使用-it
旗帜在容器内运行交互式壳。
一旦进入容器,请登录 MongoDB root管理帐户:
1[environment second]
2mongo -u mongodbuser -p
您将被提示在docker-compose.yml
文件中将您输入的密码作为MONGO_INITDB_ROOT_PASSWORD
变量值,您可以通过在mongodb
服务中设置MONGO_INITDB_ROOT_PASSWORD
新值来更改密码,在这种情况下您将不得不重新运行docker-compose up -d
命令。
运行显示 dbs;
命令列出所有数据库:
1[environment third]
2show dbs;
您将看到以下结果:
1[secondary_label Output]
2admin 0.000GB
3config 0.000GB
4local 0.000GB
55 rows in set (0.00 sec)
admin
数据库是一个特殊的数据库,它授予用户管理权限. 如果用户读取了对admin
数据库的访问权限,他们将有读取和写入所有其他数据库的权限.由于输出列出了admin
数据库,用户可以访问该数据库,因此可以读取和写入所有其他数据库。
保存第一个任务笔记将自动 创建 MongoDB 数据库。 MongoDB 允许您使用使用数据库
命令切换到不存在的数据库。当文档保存到集合时,它会创建数据库。因此,数据库不是在这里创建的;这将发生在您从 API 存储数据库中的第一个任务笔记时。执行使用
命令切换到flaskdb
数据库:
1[environment third]
2use flaskdb
接下来,创建一个新用户,该用户将被允许访问该数据库:
1[environment third]
2db.createUser({user: 'flaskuser', pwd: 'your password', roles: [{role: 'readWrite', db: 'flaskdb'}]})
3exit
此命令会创建一个名为 flaskuser的用户,该用户可以访问readWrite
的flaskdb
数据库,请确保在pwd
字段中使用安全密码。
使用以下命令登入身份验证的数据库:
1[environment third]
2mongo -u flaskuser -p your password --authenticationDatabase flaskdb
现在您已经添加了用户,请退出数据库。
1[environment third]
2exit
最后,走出容器:
1[environment second]
2exit
您现在已经为您的 Flask 应用程序配置了专用数据库和用户帐户. 数据库组件已准备好,因此您现在可以继续运行 Flask to-do 应用程序。
步骤 7 – 运行 Flask To-do 应用程序
现在,你的服务已经配置和运行,你可以通过浏览器中导航到http://your_server_ip
来测试你的应用程序,此外,你可以运行curl
来查看Flask的JSON响应:
1curl -i http://your_server_ip
您将收到以下答案:
1[secondary_label Output]
2{"message":"Welcome to the Dockerized Flask MongoDB app!","status":true}
Flask 應用程式的配置是從「docker-compose.yml」檔案傳送到應用程式,對資料庫連接的配置是使用在「flask」服務的「環境」部分定義的「MONGODB_*」變量設定的。
要测试一切,请使用 Flask API 创建一个任务笔记,您可以通过POST
曲线请求到/todo
路径来完成此操作:
1curl -i -H "Content-Type: application/json" -X POST -d '{"todo": "Dockerize Flask application with MongoDB backend"}' http://your_server_ip/todo
此请求结果是一个响应,状态代码为201 CREATED
,当任务项目被保存到 MongoDB:
1[secondary_label Output]
2{"message":"To-do saved successfully!","status":true}
您可以从 MongoDB 列出所有要做的笔记,并将 GET 请求列入 `/todo’ 路线:
1curl -i http://your_server_ip/todo
1[secondary_label Output]
2{"data":[{"id":"5c9fa25591cb7b000a180b60","todo":"Dockerize Flask application with MongoDB backend"}],"status":true}
通过此,您已经 Dockerized Flask API 运行了一个 MongoDB 备份端,使用 Nginx 作为向您的服务器部署的反向代理程序. 对于生产环境,您可以使用sudo systemctl enable docker
来确保您的 Docker 服务在运行时自动启动。
结论
在本教程中,您部署了一个Flask应用程序与Docker,MongoDB,Nginx和Gunicorn. 您现在有一个运行现代的无状态API应用程序,可以扩展。 虽然您可以通过使用一个命令,如docker container run
来实现这个结果,但docker-compose.yml
可以简化您的工作,因为这个堆栈可以被放入版本控制和必要时更新。
从这里,您还可以看看我们进一步的Python Framework教程(https://andsky.com/tags/python-frameworks?type=tutorials)。