Docker 发布 Django-uwsgi-Nginx服务,使用 Supervisor 启动 celery 服务

现如今,通过 Docker 将服务封装成镜像来部署变得越来越流行。通过这种方式可以极大的节省发布时间,也可以方便的测试人员对服务进行测试,同时还可以避免运行环境不同导致的各种服务发布问题。

本文将介绍通过 Docker 封装 Django2.2 的服务,通过 uWSGI 和 Nginx 来实现高并发。通过 Supervisor 来启动服务和 Celery 任务。本文使用的 Python 版本为 3.7,假设服务部署在 /opt 目录下面,以 app 命名项目。

服务测试

1. runserver 直接启动

首先确保服务能够通过 runserver 启动,通常启动方式如下:

python3 /opt/app/manage.py runserver 127.0.0.1:8080

此时服务会以 8080 端口启动,可以通过访问 8080 端口查看服务是否启动正常。这也是开发过程中常用的调试方式。

2. uWSGI 启动服务

如果服务启动正常,就可以测试通过 uWSGI 启动服务。

uWSGI 是一个 Web 服务器,它实现了 WSGI 协议、uwsgi、http 等协议。

在安装uWSGI之前,需要安装软件所依赖的 Python 开发文件:

sudo apt-get install python3-dev

然后通过 pip 安装 uWSGI 服务

sudo pip3 install uwsgi

高版本的 pip 不再使用 pip3,因此上面的命令也可能是下面这样的

sudo pip install uwsgi

通过命令行将站点的基本信息传递给uWSGI服务进行测试。

uwsgi --http :8080 --home /opt/app/venv --chdir /opt/app -w firstsite.wsgi

–home 告诉 uWSGI 使用 venv 目录中的虚拟环境
–chdir 切换到项目根目录,并使用存储在 firstsite 项目中的 wsgi.py 文件来提供相关服务(该文件自动生成)
此时服务还是以8080端口启动,你将再次看到你的站点。但是静态文件, 在 static 中的文件也许无法加载,这个会在后面 Nginx 服务启动后解决。

3. 创建 uWSGI 的配置文件

你可以在项目的目录下面直接创建 uwsgi.ini 文件,具体内容可以参照下面。同时也需要创建一个目录 uwsgi 用于存储 uWSGI 服务的运行状态文件。

# uwsgi.ini 
[uwsgi]

chdir = /opt/app
module = firstsite.wsgi

master = true
processes = 10
enable-threads = true

socket = 127.0.0.1:8080
listen = 100
vacuum = true

stats = %(chdir)/uwsgi/uwsgi.status
pidfile = %(chdir)/uwsgi/uwsgi.pid

log-maxsize = 500000000
req-logger = file:/tmp/reqlog
logger = file:/tmp/errlog

此时服务可以通过 uwsgi --ini /opt/app/uwsgi.ini 进行启动。

4. 配置Nginx作为反向代理服务器

安装Nginx作为反向代理

sudo apt-get install nginx

在项目目录下面添加 uwsgi_param 文件,内容如下:

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

创建服务器块配置文件

sudo vi /etc/nginx/sites-available/firstsite

放入以下内容:

server {
    listen      80;
    server_name your.site.com 127.0.0.1;
    charset     utf-8;

    client_max_body_size 75M;

    location /static {
        alias /opt/app/static;
    }

    location / {
        uwsgi_pass  127.0.0.1:8080;
        include     /opt/app/uwsgi_params;
    }
}

将新配置文件链接到 Nginx 的启用站点目录:

sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled

测试配置文件

sudo nginx -t

如果未检测到语法错误,则可以重新启动Nginx服务以加载新配置:

sudo systemctl restart nginx

目前服务以 80 端口进行启动,如果访问正常,说明服务已经可以通过Nginx 进行访问。

5. 通过 supervisor 启动和管理服务

supervisor 可以帮助我们启动和管理 uWSGI 和 Celery 服务。

[unix_http_server]
file=/var/run/supervisor.sock

[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[program:uwsgi]
autorestart=True
autostart=True
redirect_stderr=True
startsecs=10
satrtretries=3
command=uwsgi --ini /opt/app/uwsgi.ini
directory=/opt/app
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups = 10
stdout_logfile = /opt/app/logs/uwsgi_stdout.log
stopasgroup=true
killasgroup=true

[program:celery_worker]
autorestart=True
autostart=True
redirect_stderr=True
startsecs=10
satrtretries=3
command=celery -A firstsite worker -l info
directory=/opt/app
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups = 10
stdout_logfile = /opt/app/logs/celery_worker_stdout.log
stopasgroup=true
killasgroup=true

[program:celery_beat]
autorestart=True
autostart=True
redirect_stderr=True
startsecs=10
satrtretries=3
command=celery -A firstsite beat -l info
directory=/opt/app
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups = 10
stdout_logfile = /opt/app/upload/logs/celery_beat_stdout.log
stopasgroup=true
killasgroup=true

镜像打包

镜像通过基础镜像发布镜像分层构建。

1. 基础镜像创建

基础镜像包含应用启动所需的依赖软件包,可以帮助我们在更新发布镜像时节省构建时间。
dockerfile_base 的内容如下:

FROM ubuntu:18.04
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list && \
    apt-get clean && \
    apt-get update -y && \
    apt-get install -y \
        locales\
        git \
        python3 \
        python3-dev \
        python3-setuptools \
        python3-pip \
	    nginx && \
	localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && \
    pip3 install --upgrade setuptools pip -i https://pypi.tuna.tsinghua.edu.cn/simple && \
    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple uwsgi==2.0.18 supervisor==4.1.0 && \
    mkdir /opt/app && \
    mkdir /etc/supervisor && \
    echo_supervisord_conf > /etc/supervisor/supervisord.conf && \
    mkdir -p /opt/app/upload
ENV TZ=Asia/Shanghai
RUN set -eux; \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime; \
    echo $TZ > /etc/timezone
ENV LANG en_US.utf8
ENV PYTHONUNBUFFERED 1
ENV PYTHONIOENCODING UTF-8
WORKDIR /opt/app
COPY requirements.txt /opt/app/
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

新建一个目录,放置以下文件:

requirements.txt
dockerfile_base

假设 dockerfile 的文件名为 dockerfile_base,通过运行以下命令进行基础镜像构建。

sudo docker build --rm -t app:v0 -f dockerfile_base .

2. 发布镜像构建

在刚才的目录创建另一个 dockerfile 文件,命名为 dockerfile_publish
内容如下:

FROM app:v0
WORKDIR /opt/app
COPY app/. /opt/app/
COPY app/nginx.conf /etc/nginx/sites-available/default
COPY app/supervisord.conf /etc/supervisor/
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt && \
    mkdir /var/log/supervisor && \
    touch /var/log/supervisor/supervisord.log && \
    touch /var/run/supervisor.sock && \
    chmod 777 /var/log/supervisor/supervisord.log && \
    chmod 777 /var/run/supervisor.sock && \
    chmod +x /etc/supervisor/supervisord.conf && \
    chmod +x /opt/app/start.sh
EXPOSE 80
VOLUME ["/opt/app/upload"]
ENTRYPOINT ["/opt/app/start.sh"]

然后将项目文件放置在 app 目录下面。目录下面现在有以下目录和文件:

app
requirements.txt
dockerfile_base
dockerfile_publish

然后运行发布镜像的构建命令:

sudo docker build --rm -t app:v1 -f dockerfile_publish .

此时一个名为 app,标签为 v1 的镜像会构建出来。
服务的启动路径为 start.sh,包含服务启动所需的命令。

#!/bin/sh

/etc/init.d/nginx start
supervisord -c /etc/supervisor/supervisord.conf

你可能感兴趣的:(Django,Docker,docker,django,nginx)