• Docker构建nginx+uwsgi+flask镜像(一)


    前言

    笔者之前是从事Java方面的工作,自从18年5月左右来到新的公司,接触到Python,被其简单优雅的语法风格深深吸引,同时,新公司也帮助笔者打开Docker世界的大门,让笔者体会到“一次打包,到处运行”的快感。出于对Docker和Python的喜爱,写下这篇文章。

    基础工作

    这里,笔者会先教大家用命令行一步一步制作镜像,启动uwsgi+flask,再用nginx反向代理。最后,利用Dockerfile制作基础镜像和打包应用。

    首先,我们需要一个alpine3.8环境:

    [root@docker]# docker run -it docker.io/alpine:3.8 /bin/sh
    Unable to find image 'docker.io/alpine:3.8' locally
    Trying to pull repository docker.io/library/alpine ... 
    3.8: Pulling from docker.io/library/alpine
    Digest: sha256:46e71df1e5191ab8b8034c5189e325258ec44ea739bba1e5645cff83c9048ff1
    Status: Downloaded newer image for docker.io/alpine:3.8
    / # 
    

        

    alpine是一款较ubuntu和centos更为干净轻巧的Linux系统,alpine镜像的大小要比ubuntu小的多,同时也去除很多ubuntu系统自带的命令和安装程序,像ubuntu自带Python2的运行环境,而笔者此次要搭建的Python3环境,那么自带Python2的ubuntu镜像就显得有些累赘了。

    容器启动成功后,我们需要安装一些命令,我们配置清华的镜像地址便于更快的安装命令,alpine安装命令为apk add……,类似ubuntu的apt-get和centos的yum:

    / # echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.8/main/" > /etc/apk/repositories
    

      

    然后,我们通过apk命令安装vim、nginx、Python3、uwsgi等应用,注意,这里还需要安装uwsgi-python3插件:

    / # apk add --no-cache vim nginx python3 uwsgi uwsgi-python3
    fetch https://mirror.tuna.tsinghua.edu.cn/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
    (1/21) Installing pcre (8.42-r0)
    (2/21) Installing nginx (1.14.2-r0)
    ……
    OK: 97 MiB in 34 packages
    

      

    安装完Python3后,我们建立软连接以方便执行命令,并升级pip,安装flask:

    / # ln -s /usr/bin/python3 /usr/bin/python
    / # ln -s /usr/bin/pip3 /usr/bin/pip
    / # python -m pip install --upgrade pip
    Collecting pip
    ……
    Successfully installed pip-18.1
    / # pip install flask
    Collecting flask
    ……
    Successfully installed Jinja2-2.10 MarkupSafe-1.1.0 Werkzeug-0.14.1 click-7.0 flask-1.0.2 itsdangerous-1.1.0
    

      

    我们在根目录下建立app目录,创建并编辑app.py,作为我们的flask应用程序存放目录:

    / # mkdir /app
    / # cd /app/
    /app # vi app.py
    /app # cat app.py 
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello World!!!
    '
    
    
    if __name__ == '__main__':
        app.run()
    

      

    之后,我们创建并编辑uwsgi.ini文件,作为uwsgi应用程序的配置,然后用nohup启动uwsgi:

    /app # vi uwsgi.ini
    /app # cat uwsgi.ini 
    [uwsgi]
    uwsgi-socket    = 127.0.0.1:9000
    callable        = app
    plugin          = python3
    wsgi-file       = app.py 
    buffer-size     = 65535
    
    /app # nohup uwsgi --ini uwsgi.ini &
    

      

    这里笔者先介绍下uwgi的每个参数:

    • uwsgi-socket:uwsgi协议的地址和端口号。
    • callable:设置在收到请求时,uwsgi加载的模块中哪个变量将被调用,默认是名字为“application”的变量。
    • plugin:加载插件。
    • wsgi-file:加载指定的wsgi文件。
    • buffer-size:设置用于uwsgi包解析的内部缓存区大小。默认是4k。

    再说下笔者在uwsgi中遇到的坑:

    网上有不少教程的uwsgi配置都是直接配置socket或http-socket,一开始笔者也是配置socket和http-socket,然而不知是不是因为环境的问题,nginx用uwsgi协议一直代理不了,用http协议却可以代理,且nginx日志显示uwsgi协议访问失败,直到Google之后才知道uwsgi还有uwsgi-socket这个选项,笔者用uwsgi-socket替换之前的http-socket,就可以用nginx的uwsgi协议代理uwsgi+flask启动的服务了。这里再次表白下Google顺便吐槽下百度,百度一晚上,不如Google一分钟。

    其次是plugin,网上有的教程配置plugin为python,但笔者不配置plugin会被uwsgi要求配置,但是将plugin配置为python,又会报无法打开/usr/lib/uwsgi/python_plugin.so文件,于是笔者到/usr/lib/uwsgi/目录下看了这个目录下的文件,有一个python3_plugin.so,于是笔者将plugin配置为python3,就可以用uwsgi命令读取uwsgi.ini文件启动服务了。

    启动了uwsgi+flask服务,接下来便是启动nginx了,在启动nginx之前,我们先要配置一下nginx.conf文件。我们在/etc/nginx目录下的nginx.conf文件中<1>处配置pid选项,这是一个目录,用于保存nginx的进程号,默认保存进程号的目录不存在,如果不修改这个配置,会报错。同时,我们还需要在http模块下的<2>处配置uwsgi协议反向代理到我们uwsgi+flask应用:

    /app # cd /etc/nginx/
    /etc/nginx # cat nginx.conf 
    # /etc/nginx/nginx.conf
    
    # <1>配置pid选项
    pid /var/run/nginx.pid;
    
    ……
    
    http {
    		# <2>配置uwsgi协议反向代理
            server {
                    listen 6666;
                    charset UTF-8;
                    client_max_body_size 75M;
                    location / {
                            include uwsgi_params;
                            uwsgi_pass 127.0.0.1:9000;
                            uwsgi_buffer_size 32k;
                            uwsgi_buffers 8 32k;
                            uwsgi_busy_buffers_size 32k;
                    }
    
            }
    		……
    
    }
    

      

    然后,启动nginx,并回到app目录下,通过wget命令,访问nginx监听的6666端口,我们会获取到一个index.html文件,打印html文件,可以看到是我们app.py文件所返回的“Hello World!!!”内容。

    /etc/nginx # nginx 
    /etc/nginx # cd /app/
    /app # wget http://127.0.0.1:6666/
    Connecting to 127.0.0.1:6666 (127.0.0.1:6666)
    index.html           100% |********************|    15   0:00:00 ETA
    /app # cat index.html 
    Hello World!!!
    

      

    至此,我们就完成了在alpine容器中搭建nginx+uwsgi+flask的服务了。但我们还缺了一步,将宿主机的端口和容器中的端口进行映射,这一步将在后面用Dockerfile制作基础镜像和打包应用向大家展现。另外,大家可以尝试一下将uwsgi.ini配置中的uwsgi-socket改成http-socket,然后尝试nginx配置在不改动的情况下,是否还能正常代理。并且在尝试完后,再将nginx之前所设置的server模块改写成如下:

    server {
            listen 6666;
            charset UTF-8;
            client_max_body_size 75M;
            location / {
                    proxy_read_timeout 300;
                    proxy_connect_timeout 300;
                    proxy_pass http://127.0.0.1:9000;
            }
    
    }
    

      

    然后重启nginx,看看修改完nginx配置后是否能正常代理。

     

  • 相关阅读:
    Ubuntu安装tomcat
    mongodb配置数据库文件夹,创建服务
    chrome 49 版本bug: flex父元素设置flex:1 , 子元素用height:100%无法充满父元素
    angularjs指令中的require赋值含义
    flex布局在垂直居中里,元素超过容器大小后,不能通过滚动条滚动到顶端,这是个flex的bug
    redux中的compose源码分析
    js中的reduce()函数
    redux-thunk中间件源码
    HTML, CSS. JS的各种奇淫技巧
    JS在项目中用到的AOP, 以及函数节流, 防抖, 事件总线
  • 原文地址:https://www.cnblogs.com/beiluowuzheng/p/10219506.html
Copyright © 2020-2023  润新知