如何使用 MongoDB 和 Docker 设置 Flask

作者选择了 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 服务器,来服务应用程序。

前提条件

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

步骤 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_namemongodb,其重新启动策略为unless-stopped。您使用命令属性来定义在启动容器时将执行的命令。

环境变量 MONGO_INITDB_ROOT_USERNAMEMONGO_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

在这里,您已经定义了构建背景,即包含Dockerfilenginx文件夹。使用图像属性,您指定了用于标记和运行容器的图像。端口属性将配置 Nginx 服务以通过:80:443进行公开访问,而nginxdata的卷插入容器中的/var/log/nginx目录。

您已将 Web 服务器服务depends_onflask的服务定义,最后网络属性定义了网络的 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,appdatanginxdata为您的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_logaccess_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-PyMongorequests. 将以下内容添加到 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,requestjsonify对象来实时化应用程序,处理请求,并分别发送 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-dosdb.todo.find()方法返回了数据库中的所有to-dos。接下来,您重复了_todos来构建一个项目,其中仅包含将它们附加到data数组的对象中的idtodo,并最终返回为 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_DEBUGENVIRONMENT_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_USERNAMEMONGO_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的用户,该用户可以访问readWriteflaskdb数据库,请确保在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)。

Published At
Categories with 技术
comments powered by Disqus