文章目录
- 零、系列目录
- 一、基本概念
- 1、Docker
- 2、Nginx
- 3、uWSGI
- 4、Flask
- 二、部署结构
- 三、结构分析
- 四、实现步骤
- 1、编写 Flask 应用
- 2、编写 uWSGI 配置文件
- 3、编写 Nginx 配置文件
- 4、编写 Docker 启动脚本
- 5、编写 Docker 镜像构建文件
- 6、编写 docker-compose 文件
- 五、测试
- 1、运行
- 2、检查启动服务
- 3、检查返回结果
- 六、总结
零、系列目录
写这套文章的时候,不会完全按照目录的顺序一篇一篇写, 大家可以到目录中直接找到对应的章节进行查看。
点我跳转
一、基本概念
在开始真正的操作之前,我们先明确一下标题中提到的几个名词的基本概念,以便大家更好的理解后面的内容。
1、Docker
Docker 是目前最流行的 Linux 容器解决方案。说起来比较抽象,可以理解为轻量级的虚拟机。
2、Nginx
Nginx 是一款轻量级的 HTTP 服务器
,采用事件驱动的异步非阻塞处理方式框架,这让其具有极好的 IO 性能,时常用于服务端的反向代理和负载均衡。
3、uWSGI
在介绍 uWSGI
之前我们先了解一下其他两个概念:WSGI
和 uwsgi
。
- WSGI
WSGI 是
Web 服务器网关接口(Web Server Gateway Interface)
的缩写,它是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。
- uwsgi
uwsgi (注意此处是小写)是一个 uWSGI 服务器特有的
通讯协议
。
- uWSGI
uWSGI 是一个
Web 服务器
,它实现了 WSGI、uwsgi、http 等协议。
简单来说, WSGI
和 uwsgi
都是通讯协议,uWSGI
是服务器(软件)。
4、Flask
Flask 是一个使用 Python 编写的轻量级 Web 应用框架
。
二、部署结构
首先,我们是要部署一个 Docker
容器,容器里面要包括 Nginx
、uWSGI
、Flask
框架编写的程序。结构大致如下图所示:
三、结构分析
为什么要采用这样一套环境来部署呢?
答案也很简单,因为性能。
如果是单纯为了把写好的 Flask
应用放到 Docker
中运行的话, 只需要一行启动脚本就可以:
python run.py
这样就把 Flask
应用启动起来了,就像在本地开发时一样。
但这样做有一个致命的问题:不支持并发。
当我们直接在控制台启动一个 Flask
应用时,会得到如下的输出:
$ python run.py
* Serving Flask app "run" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Do not use it in a production deployment
明晃晃,亮瞎眼。
上面我们提到的 Nginx
+ uWSGI
+ Flask
的方式,就是 Flask
官方推荐的一种生产环境的部署方式。我们现在要做的,就是把这套环境放到 Docker
里面而已。
四、实现步骤
本文使用的示例代码位置:点我跳转。
1、编写 Flask 应用
我们先创建一个简单的 Flask 应用,新建 run.py
文件,内容如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, B~ia~tch'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
本地启动一下试试:
$ python run.py
* Serving Flask app "run" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
OK,访问 localhost:5000
就会看到返回值:
$ curl localhost:5000
Hello, B~ia~tch
同时,看到启动 Flask 的控制台输出如下内容:
127.0.0.1 - - [09/Mar/2021 14:08:15] "GET / HTTP/1.1" 200 -
这说明我们的 Flask 应用已经可以了。
2、编写 uWSGI 配置文件
增加配置文件 uwsgi.ini
,内容如下:
[uwsgi]
chdir = /code
wsgi-file = run.py
socket = :5000
callable = app
chmod-socket = 666
plugins = python3
buffer-size = 65535
processes = 4
threads = 2
更多关于 uWSGI
配置文件、配置信息的内容可以参考这里:点击跳转。
3、编写 Nginx 配置文件
增加配置文件 nginx_uwsgi.conf
,内容如下:
server {
listen 9999;
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
uwsgi_send_timeout 300;
uwsgi_connect_timeout 300;
uwsgi_read_timeout 300;
}
}
其中,9999
表示 Nginx
的监听端口,5000
表示 uwsgi.ini
当中配置的 socket
的值。
更多关于 Nginx
配置文件的内容可以参考这里:点击跳转。
4、编写 Docker 启动脚本
增加启动脚本文件 start_script.sh
,内容如下:
# start nginx
service nginx start
# start uwsgi
uwsgi --ini uwsgi.ini
# prevent container from exiting
tail -f /var/log/nginx/error.log
其中最后一句是为了防止容器启动后自动退出的。
可能有的同学会问了,怎么不启动 Flask 应用呢?没有看到启动的语句呀。
你可真是个聪明的小机灵。
Flask
由 uWSGI
直接调用,这就类似 PHP-FPM
调用 PHP
一样。
这里咱们用上了前面创建的 uwsgi.ini
文件,用它来启动 uWSGI
服务。
5、编写 Docker 镜像构建文件
增加 Dockerfile
,内容如下:
FROM python:3.6
ADD . /code
WORKDIR /code
# install python library
RUN python3 -m pip install -r requirements.txt -i http://pypi.tuna.tsinghua.edu.cn/simple
# update source list
RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN sed -i s@/security.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean
# install packages
RUN apt-get update \
&& apt-get install -y nginx uwsgi uwsgi-plugin-python3
# copy nginx config file
COPY nginx_uwsgi.conf /etc/nginx/conf.d
CMD ["/bin/sh", "start_script.sh"]
这里都是基础的 Docker 构建镜像内容了,需要注意的是,一定要安装 uwsgi
、uwsgi-plugin-python3
这两个软件/服务。
再就是,前面创建的 nginx_uwsgi.conf
这里也用上了,放到 Nginx
的配置文件目录中去。
6、编写 docker-compose 文件
增加 docker-compose.yml
文件,内容如下:
version: '3.3'
services:
nginx_uwsgi_flask:
build: .
container_name: nginx_uwsgi_flask
ports:
- "9999:9999"
volumes:
- .:/code
restart: always
我比较懒,喜欢用
docker compose
。
这里注意需要映射的是 Nginx
中配置的 9999
端口。
五、测试
1、运行
使用 docker compose
构建镜像并运行,执行以下命令:
docker-compose up -d
看到类似如下的输出,说明创建成功。
Successfully built e3d41df6fa4d
Successfully tagged 01_docker_nginx_uwsgi_flask_nginx_uwsgi_flask:latest
WARNING: Image for service nginx_uwsgi_flask was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating nginx_uwsgi_flask ... done
2、检查启动服务
进入容器:
$ docker exec -it nginx_uwsgi_flask bash
root@19a436d48cd8:/code#
查单当前运行的服务:
root@19a436d48cd8:/code# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:12 ? 00:00:00 /bin/sh start_script.sh
root 18 1 0 07:12 ? 00:00:00 nginx: master process /usr/sbin/nginx
www-data 19 18 0 07:12 ? 00:00:00 nginx: worker process
www-data 20 18 0 07:12 ? 00:00:00 nginx: worker process
root 21 1 0 07:12 ? 00:00:00 uwsgi --ini uwsgi.ini
root 22 21 0 07:12 ? 00:00:00 uwsgi --ini uwsgi.ini
root 23 21 0 07:12 ? 00:00:00 uwsgi --ini uwsgi.ini
root 24 21 0 07:12 ? 00:00:00 uwsgi --ini uwsgi.ini
root 34 0 0 07:14 pts/0 00:00:00 bash
root 40 34 0 07:14 pts/0 00:00:00 ps -ef
可以看到,启动的服务包括一个 Nginx
的 master
进程,两个 Nginx
的 worker
进程,四个 uwsgi
进程。
服务都正常启动了。
3、检查返回结果
在宿主机执行请求:
$ curl localhost:9999
Hello, B~ia~tch
端口 9999
,说明我们访问的是 Docker
的容器,得到了期望的返回值。
大功告成。
剩下的就是完善 Flask
的业务代码了。
六、总结
本文使用的示例代码位置:点我跳转。
今天与大家分享了一个基于 Docker
部署 Nginx
+ uWSGI
+ Flask
应用的例子,已经看到结尾,相信大家也一定有所收获。
这个示例很基础,简单拿来用一用还是可以的。
祝大家变的更强。