基于docker+gunicorn部署sanic项目踩过的坑

基于docker+gunicorn部署sanic项目踩过的坑基于docker+gunicorn部署sanic项目踩过的坑

大家好,欢迎来到IT知识分享网。

前言:

最近有个项目需要上线,是python中sanic网络异步框架写的,并且要求使用docker+nginx来部署项目实现负载均衡,于是乎百度了sanic项目部署,基本上都是基于docker+gunicorn部署sanic项目这篇文章,里面讲的也稍稍微有些简略,不过对于小白特别不友好,按步骤操作肯定是不行的,因为文章中只举了很小很小的一个例子,感觉更像demo。而小白可能只是临时接受部署任务,按部就班的操作是会出现很多错误的。现在就来排排坑。(建议先看一遍再动手部署)

一、Dockerfile文件放在哪?

基于docker+gunicorn部署sanic项目踩过的坑

这是sanic项目的总目录,首先明确一点我的主运行文件是run.py,所以Dockerfile需要放在和我主文件相同地方,这样执行build指令就可以直接在当前目录下创建。可以直接使用vim指令在该项目目录下创建Dockerfile,记住文件名一定要相同

二、Dockerfile里面写什么?为什么要写

FROM taoliu/gunicorn3 WORKDIR /temp1 ADD . /temp1 RUN pip install --upgrade pip RUN pip install -r requirements.txt -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com EXPOSE 9010 CMD gunicorn run:app --bind 0.0.0.0:9010 --worker-class sanic.worker.GunicornWorker 

下面一个个来解释

FROM:表示这个镜像是基于什么创建的,也就是基础镜像,这里使用taoliu/gunicorn3表示我使用的是gunicorn3来运行我的镜像,可以理解为项目需要一个环境来运行。而这个镜像是国内的,所以下载会较快

WORKDIR:表示工作目录是在docker中的哪里,可以稍微理解一下docker是个独立的系统,就像安装在Windows中虚拟机虚拟的linux,和外面的Windows命令和目录是不相互关联的。而这个目录也是我们后面执行命令所在的目录。

ADD:这里使用ADD . /temp1,前面的“.”表示将当前所在目录的所有文件全部放到docker中的/temp1这里要和上面的WORKDIR设置的一样,命名按照自己喜欢的来,这里是测试就用temp1代替

RUN:就相当于开始运行指令(可以理解为在linux中输入命令行,但其实这是在docker环境中输入的)了,docker中的系统一些python依赖的库是不存在的,所以我们开始先更新一下docker中的pip,再由pip获取项目所需镜像,这里我整理到了固定的文件内即requirements.txt,推荐使用国内镜像。这样下载较快,我使用的是阿里云镜像。

EXPOSE:设置镜像暴露端口,记录容器启动时监听哪些端口,容器启动时,Docker Daemon会扫描镜像中暴露的端口,如果加入-P参数,Docker Daemon会把镜像中所有暴露端口导出,并为每个暴露端口分配一个随机的主机端口(暴露端口是容器监听端口,主机端口为外部访问容器的端口)

注意:EXPOSE只设置暴露端口并不导出端口,只有启动容器时使用-P/-p才导出端口,这个时候才能通过外部访问容器提供的服务

CMD:设置容器的启动命令,也就是当我们启动容器的时候执行的命令,我的项目端口是0.0.0.0:9010,文件是run,所以使用gunicorn3启动时,命令为上述文件中。需要注意的是Dockerfile中只能有一条CMD命令,如果写多了则最后一条生效

三、build镜像

上面的步骤处理完之后就可以build出新镜像了,使用下面命令:

sudo docker build -t sanic_item . 

这里千万要加后面的点,代表当前路径下创建镜像

四、使用run还是使用create+start

在对于新技术肯定要经过较多的测试才能很好的掌握,如果使用下面这条命令:

sudo docker run --name sanic1 -p 8080:8080 sanic_item 

–name:为容器起个别名,这样可以使用这个别名操作容器,而不需要用随机的容器ID来进行操作

-p:来指定端口,前面的端口是linux的,后面的端口是docker中项目运行的端口,两个可以一样可以不一样。但是为了方便开发及测试,建议尽量一样.

后面就是镜像名了。而这条run语句就等于create+start即创建并开启容器。这里说一下容器是基于镜像来运行的。关于容器和镜像的关系要深入docker中了解。这里不详细介绍。这条语句的弊端就是第一次使用的部署可以使用,但是如果第二次还使用,那么就会不停的创建新容器。在不了解的情况下,以为run指令只会运行镜像。没想到docker中是根据镜像来创建容器再运行。滥用run指令的结果图:

基于docker+gunicorn部署sanic项目踩过的坑

可以看出很多是基于一个镜像来创建的容器。其实第一次使用完run之后便可使用一些经常使用的命令:

sudo docker stop sanic1 #停止当前运行的容器,前提是run指令时有--name来指代名字 sudo docker start sanic1 #只需要启动就行,不需要再用run或create sudo docker ps #查看当前运行镜像 sudo docker ps -a #查看当前容器状态,正在运行的容器PORTS列会有参数,上图就是没有容器正在运行 sudo docker rmi 镜像ID/别名 #需要先使用ps指令找到要删除的镜像ID再删除 sudo docker rm 容器ID/别名 #比如删除sanic1这个容器sudo docker rm sanic1 

五、使用nginx实现负载均衡

首先明确一点一个端口不能同时被两个程序所占用。就打个比方来说,现在的项目前端发来的请求访问的是8080端口,如果是单机版项目,直接运行监听8080即可。但是目前遇到的情况是项目部署在docker上,还要启动nginx来监听。也就会造成这个端口有两个进程在监听,这时候只能启动一个。并且我们要部署多个后台服务。所以首先考虑nginx。我的nginx配置文件如下(注意看中文注释部分)

http { #代表HTTP协议其他的协议需要其他定义
 include mime.types;
 default_type application/octet-stream;
 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' #这里规定的是日志的输出格式,建议打开
 '$status $body_bytes_sent "$http_referer" '
 '"$http_user_agent" "$http_x_forwarded_for"';
  
 #access_log logs/access.log main;
  
 sendfile on;
 #tcp_nopush on;
 #keepalive_timeout 0;
 keepalive_timeout 65;
 #gzip on;
  server{ 
 listen 8080;#监听8080端口
 server_name localhost;
    access_log /usr/logs/host1.access.log main;#开启日志功能,只要访问这个端口的都会有输出,具体的名字和目录自己指定,main为上面定义的日志格式
 location /{
   proxy_pass http://localhost; #对于发送到8080端口的请求可以进行转发
   }
 }
  server { #nginx默认服务,这里只需要放入前端界面即可
 listen 80;
 server_name localhost;
 #charset koi8-r;
 access_log /usr/logs/host.access.log main; #不同端口我建立了不同日志,必须要保证日志所在目录有效才会创建,同时日志我这里没设置无缓存刷出,若要看见实时消息的才设置
 root /usr/local/dist2/;
 # location / {
 # root html;
 # index index.html index.htm;
 location /{
 index index.html index.htm;
   }
 }
 upstream localhost{#这里是实现负载均衡的策略,我的上一篇博客中介绍过为什么使用这种方法
 ip_hash; 
 server 0.0.0.0:9010 weight=1;
 server 0.0.0.0:9011 weight=1;
 server 0.0.0.0:9012 weight=1; 
 }
}#这里代表HTTP协议的请求即定义的服务完成

可以看到我们对于8080端口的请求,转发到了9010,9011,9012三个端口,那么docker需要准备三个不同镜像,来创建三个不同容器,这样才能实现nginx的代理。对于sanic项目只需要改一下运行端口即可,其余部分相同,Dockerfile中的端口也要与其对应。比如我当前的sanic项目改了三个不同端口为9010,9011,9012。(对应上面讲的Dockerfile也要变),然后build三个不同镜像为sanic_item1,sanic_item2,sanic_item3。然后启动三个命令窗口输入下面的指令

sudo docker run --name sanic1 -p 9010:9010 sanic_item1 sudo docker run --name sanic2 -p 9011:9011 sanic_item2 sudo docker run --name sanic3 -p 9012:9012 sanic_item3 

便能运行三个容器了。

注意:这里介绍的是纵向扩展的负载均衡架构,也是一个介绍。如果多台其实只要改ip地址即可,端口可以不改变。这里所说的docker+nginx实现负载均衡,不需要Nginx部署在docker内部,Nginx只是一个请求转发的工具,如果是遇到上千万级请求或上亿级,超过了nginx的负荷才需要部署多台。主要的压力还是在后端和前端处理和解析数据上。

总结:

目前使用sanic项目部署的资料特别少,遇到的一些bug很难查找,希望对遇到相同问题的人有用。

null

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/91098.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信