docker容器化python服务部署(supervisor-gunicorn-flask)

时间:2022-01-14 07:03:56

docker容器化python服务部署(supervisor-gunicorn-flask)

本文系作者原创,转载请注明出处: https://www.cnblogs.com/further-further-further/p/13223767.html

目录

  • 实现目标

  • docker vs virtual machine(虚拟机)

  • 实战(python 服务镜像制作,本地镜像仓库创建,移植)

  • 遇到的问题以及解决办法


  • 实现目标

>  在局域网内机器上部署 python 服务(在某台机器上部署完成后,生成镜像,上传到本地镜像仓库,其他机器下载镜像,一键部署服务);

> 开机自启动(物理机启动->容器自启动->服务自启动)

  • docker vs virtual machine(虚拟机)

啥也不说,先上docker官方网站的两张图。

docker容器化python服务部署(supervisor-gunicorn-flask)

VM(虚拟机)

优点:在于隔离性,各个虚拟环境之间是完全隔离的。

缺点:每个虚拟环境类似于一个独立的机器,有独立的操作系统,所以占用内存比较大,一台物理机器最多也就能同时开启虚拟环境 10+,

另外,部署在虚拟环境下服务不太好移植。

docker

优点:有虚拟机隔离性的特点,解决了传统 VM 占用内存较大,服务不太好移植的问题。

关于 vm 和 docker 的详细区别,这里就不赘述了,网络上铺天盖地,大家随便百度一下。

  • 实战(python 服务镜像制作,本地镜像仓库创建,移植)

我的操作系统linux centos7,通过命令 cat /etc/os-release 查看

docker容器化python服务部署(supervisor-gunicorn-flask)

> docker 安装

注:宿主机 centos 版本最好是 7 以上,在 6 上安装 docker 遇到坑比较多。

yum install -y docker

> 获取基础镜像

docker pull centos

会自动在官网(https://hub.docker.com/)获取 centos:latest 镜像。

查看所有镜像(-a : all):

docker image ls -a

docker容器化python服务部署(supervisor-gunicorn-flask)

> 容器创建

docker container run -it -p 8888:8080 -v /opt/app:/opt/app --name=python-server 470671670cac bash

命令文档查看:docker container run --help

-it : 交互式终端(interactive terminal) ,也就是创建容器后进入容器。

-p 8888:8080 :  端口映射(port),将容器端口映射到宿主机端口(8888:宿主机端口,8080:容器端口),宿主机端口 8888 确认能被外网访问。

-v /opt/app:/opt/app:数据卷(volumn),将宿主机的数据(应用程序代码,配置文件等等)挂载到容器指定路径下,实现数据存储的持久化(如果没有数据挂载的话,容器销毁,容器中的数据会自动消失)。

--name=python-server: 新的容器的名称

470671670cac:镜像ID(imageID),当然也可以是 imageName + tag(docker.io/centos:latest)

bash:跟 -it 命令结合在一起操作,使容器创建后处于前端,一般是 /bin/bash,我这是bash。

docker容器化python服务部署(supervisor-gunicorn-flask)

表示容器已创建完成,并已进入容器,容器ID:5de4e81a2e20

可以通过 Ctrl+p,Ctrl+q 退出容器,但容器还是处于运行状态(Up)。

查看正在运行容器的状态:docker container ls 也可以是 docker ps

docker容器化python服务部署(supervisor-gunicorn-flask)

查看所有容器的状态(包含正在运行 up 和停止 exit):docker container ls  -a  == docker ps -a

退出容器后再进入容器,有两种方式(前提是该容器必须处于运行状态):

方式一:docker container exec -it 5de4e81a2e20(containerID) bash

方式二:ssh 172.17.0.4(容器ip)

查看容器ip(需要退出容器查看)

docker container inspect 5de4e81a2e20(containerID)

docker容器化python服务部署(supervisor-gunicorn-flask)

容器其他相关操作命令:

容器启动(交互式):docker container start  -i containerID

关闭容器:docker container stop containerID

容器重启动:docker container restart containerID

删除容器(-f : force 强制删除,能删除处于运行状态的容器):docker container rm -f  containerID

查看所有容器的容器ID:docker container ls -a -q

删除所有容器:docker contianer rm $(docker container ls -a -q)

在交互式容器中退出,退出启动容器: Ctrl + d

在交互式容器中退出,但是不退出启动容器:先按 Ctrl + p 后 Ctrl + q

使用 -d 启动容器并一直在后台运行 SSH作为第一进程启动:docker container run -d -p 50001:22 imageID /usr/sbin/sshd -D

安装 SSH:

SSH作用:

1. 出现问题方便进入容器调试;

2. 作为 python 服务的守护程序,防止容器闪退(一直夯在容器中);

安装命令: yum install -y openssh-server

ssh 配置文件 sshd_config 路径: /etc/ssh/

ssh 启动文件路径:/usr/sbin/

安装 passwd(设置密码): yum install -y passwd

设置密码:passwd root

new password: 12345678

启动 SSH: /usr/sbin/sshd

查看容器 ip(退出容器,在宿主机上,最好另起一个客户端): docker container inspect  1427087a62a7(containerID)

docker容器化python服务部署(supervisor-gunicorn-flask)

从宿主机进入容器:ssh 172.17.0.5 ,输入密码:12345678

安装 python3:

一般只需安装 pip3即可,但是为了服务调试,这里安装了python3,python3中包含了pip。

安装命令:yum install -y python3

安装完成后,查看版本:python3 -V

docker容器化python服务部署(supervisor-gunicorn-flask)

这里的python服务是关于深度学习的,所以需要添加库opencv,flask,interval,matplotlib,Pillow,gunicorn,gevent,supervisor。

安装 python 相关库

通过pip3安装,最好加上国内镜像源,防止网络的原因无法下载。

国内常用镜像源:

阿里云 http://mirrors.aliyun.com/pypi/simple/

中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/

豆瓣(douban) http://pypi.douban.com/simple/

清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/

中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/

>> opencv:

pip3 install opencv-python-headless==4.2.0.32 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

>> flask:

pip3 install Flask==1.1.2 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

>> interval:

pip3 install interval==1.0.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

>> matplotlib:

pip3 install matplotlib==3.2.1 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

>> gunicorn

pip3 install gunicorn==20.0.4 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

>> supervisor

pip3 install supervisor==4.0.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

>> gevent:

pip3 install gevent==20.6.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

当然也可以通过 requirements.txt 一键安装所有相关库:

将 python 相关库写入 requirements.txt中:

cat > requirements.txt <<EOF

certifi==2020.4.5.2
chardet==3.0.4
click==7.1.2
cycler==0.10.0
Flask==1.1.2
gevent==20.6.0
gpg==1.10.0
greenlet==0.4.16
gunicorn==20.0.4
idna==2.9
interval==1.0.0
itsdangerous==1.1.0
Jinja2==2.11.2
kiwisolver==1.2.0
MarkupSafe==1.1.1
matplotlib==3.2.1
meld3==2.0.1
numpy==1.18.5
opencv-python-headless==4.2.0.32
Pillow==7.1.2
pyparsing==2.4.7
python-dateutil==2.8.1
requests==2.23.0
rpm==4.14.2
six==1.15.0
supervisor==4.0.0
urllib3==1.25.9
Werkzeug==1.0.1
zope.event==4.4
zope.interface==5.1.0

EOF

查看:cat requirements.txt

一键安装:pip3 install -r requirements.txt

如果已安装完所有库,需要移植到其他机器中,打包所有 python 库:pip3 freeze > requirements.txt

> supervisor & gunicorn 配置

gunicorn 可以理解为 WSGI 协议的一个实例,WSGI(Web Server Gateway Interface):就是一个网关,是 web 服务器与应用程序之间通信的协议接口。

supervisor 提供了统一的方式来控制(start,stop,restart)进程,类似于 systemctl(在 docker 容器中 systemctl 命令是无效的)。

>> 生成 supervisord.conf

echo_supervisord_conf > /etc/supervisord.conf

>> 修改 supervisord.conf 配置

vi /etc/supervisord.conf

在文件最底部,去掉 include , files 注释,并将 files 修改为

[include]
files = /etc/supervisor/*.conf

>> 添加 gunicorn.conf

创建路径:mkdir /etc/supervisor

创建配置文件 gunicorn.conf:vi /etc/supervisor/gunicorn.conf

内容为:

[program:gunicorn]
command = gunicorn -c /opt/app/darknet_captcha/gunicorn.conf.py wsgi:application
autostart = true
startsecs = 5
autorestart = true
startretries = 3
redirect_stderr = true
stdout_logfile=/opt/app/logs/gunicorn.log

>> 配置文件生效:supervisorctl update

>> 先测试 gunicorn 启动 flask 服务

gunicorn -c /opt/app/darknet_captcha/gunicorn.conf.py wsgi:application

psc -ef|grep gunicorn

docker容器化python服务部署(supervisor-gunicorn-flask)

说明启动正常

删除 gunicorn 进程,改由 supervisord 启动

kill -9  55

>> 用 supervisord 启动 gunicorn

supervisord -c /etc/supervisord.conf

docker容器化python服务部署(supervisor-gunicorn-flask)

如果出现如下问题,说明已有进程启动,占用了端口号。

docker容器化python服务部署(supervisor-gunicorn-flask)

解决办法:删除已启动进程即可

ps -ef|grep supervisord

kill -9 pid

启动后,查看 gunicorn 是否启动。

ps -ef|grep gunicorn

docker容器化python服务部署(supervisor-gunicorn-flask)

如果服务启动失败,在日志里查看原因。

日志查看:vi /opt/app/logs/gunicorn.log

后面就可以使用如下命令操作gunicorn
supervisorctl start gunicorn
supervisorctl stop gunicorn
supervisorctl restart gunicorn

到此,在单机上 docker 容器下 flask 服务部署已完成,接下来就是

基本镜像的制作,通过 dockerfile 创建最终镜像,本地镜像仓库创建,镜像 push 到本地仓库,局域网内其他机器 pull 镜像,一键部署服务。

> 基本镜像制作

退出容器,但容器需处于运行(up)状态:Ctrl + p,Ctrl + q

查看容器ID: docker container ls

docker容器化python服务部署(supervisor-gunicorn-flask)

制作镜像(镜像名称:weixw/python-server-mirror:v1):docker commit c96c249cf2bd weixw/python-server-mirror:v1

用 docker image ls 查看新镜像是否已存在

docker容器化python服务部署(supervisor-gunicorn-flask)

> 通过 dockerfile 创建最终镜像

为什么还要通过 dockerfile 制作镜像呢,因为上面生成的基础镜像只能保存静态文件,资源,不能保存动态命令,比如 shell 相关命令,应用程序命令,

而这些命令可以通过 dockerfile 写入进来,从而达到一键创建容器就能自动启动服务的目的。

>> 创建 Dockerfile (规范名称必须是 Dockerfile 或 dockerfile)

在应用程序服务的根目录下创建 Dockerfile :

cd /opt/app/darknet_captcha

vi Dockerfile

docker容器化python服务部署(supervisor-gunicorn-flask)

>> Dockerfile 内容

docker容器化python服务部署(supervisor-gunicorn-flask)

FROM: 基础镜像

WORKDIR:  指定当前路径

COPY: 复制文件

ADD : 添加文件,有 COPY 功能,还有解压,从网站下载文件作用

EXPOSE: 暴露容器端口

CMD : shell 以及 应用程序命令

>> init.sh()

docker容器化python服务部署(supervisor-gunicorn-flask)

CMD 一般只能运行一条命令,对于多个命令,采用脚本方式运行。

>> 创建最终镜像

cd /opt/app/darknet_captcha

docker image build -t weixw/python-server-mirror:v1.2 ./

docker容器化python服务部署(supervisor-gunicorn-flask)

查看:docker image ls

docker容器化python服务部署(supervisor-gunicorn-flask)

> 本地镜像仓库创建(其他端口不太行,需要开启外网访问端口5000):

>> 下载 registry 镜像

docker pull registry

>> 启动registry容器:docker run -d -p 5000:5000 --restart=always --name registry -v /opt/registry/:/var/lib/registry registry

--restart=always : docker 启动,容器自启动

>> 修改docker 配置文件 daemon.json

vim /etc/docker/daemon.json
{
"registry-mirrors":["https://uoggbpok.mirror.aliyuncs.com"],
"insecure-registries":["120.132.8.180:5000"]
}

>> 本地仓库加安全认证

>>> 生成密码:username: root     password: 123456

yum install httpd-tools -y
mkdir /opt/registry-auth/ -p
htpasswd -Bbn root 123456 > /opt/registry-auth/htpasswd

>>> 修改密码:
cd /opt/registry-auth/
vim htpasswd

>>> 重新启动带有秘钥功能的registry容器
docker rm -f containerID
docker run -d -p 5000:5000 -v /opt/registry-auth/:/auth/ -v /opt/registry:/var/lib/registry --restart=always --name register-auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" registry

>>> 规范本地镜像名称:docker tag  imageID   120.132.8.180:5000/weixw/captcha

docker tag weixw/python-server-mirror:v1 120.132.8.180:5000/weixw/python-server-mirror:v1.2

>>> 登录(一定要先登录校验,否则无法 push):
docker login 120.132.8.180:5000
username: root
password: 123456

>>> 上传镜像到本地仓库(端口5000能被外网访问):docker push 120.132.8.180:5000/weixw/python-server-mirror:v1.2

有一个 harbor 服务用来可视化管理镜像的,大家感兴趣的话可以玩玩,因为我的Linux宿主机本来就是虚拟机,配置比较低,这里就不安装了。

> 另外一台机器获取镜像( 120.132.8.180:5000)步骤:

>> 修改docker 配置文件 daemon.json
vim /etc/docker/daemon.json
{
"registry-mirrors":["https://uoggbpok.mirror.aliyuncs.com"],
"insecure-registries":["120.132.8.180:5000"]
}

>> 重启 docker : systemctl restart docker

>> 登录(pull 一般不需要登录,可以直接下载):

docker login 120.132.8.180:5000
username: root
password: 123456

>> 向镜像仓库(120.132.8.180:5000)获取镜像: docker pull 120.132.8.180:5000/weixw/python-server-mirror

>> 一键启动服务:docker container run -d -p 80:8080 --restart=always --name=captcha_server 120.132.8.180:5000/weixw/python-server-mirror

-d: 表示在后台启动

-p: 表示端口映射(80:宿主机端口,8080:容器端口)

--restart=always:表示开机自启动容器

启动容器后查看 flask 服务是否启动:ps -ef|grep gunicorn

用 curl 或 postman 向 120.132.8.180:80/服务名称 发送请求,查看结果。

如果服务没有起来,查看日志/opt/app/logs/gunicorn.log 定位问题,然后解决问题。

  • 遇到的问题以及解决办法

> 无法强制删除镜像

原因:该镜像下有容器创建,有可能不是运行状态(exit),所以需要先删除容器,再删除镜像。

解决方案:

查找所有容器:dokcer container ls -a

删除该镜像下所有容器:docker container rm -f containerID

删除镜像:docker image rm -f imageID

> 镜像也可以保存文件,然后将文件导入

>> 将镜像保存在本地:docker save -o 本地名字 image/name

例如: docker save -o python-server.tar 120.132.8.180:5000/weixw/python-server-mirror

>> 将本地镜像文件加载进docker: docker load -i python-server.tar

不要让懒惰占据你的大脑,不要让妥协拖垮了你的人生。青春就是一张票,能不能赶上时代的快车,你的步伐就掌握在你的脚下。

docker容器化python服务部署(supervisor-gunicorn-flask)的更多相关文章

  1. 通过 Azure Pipelines 实现持续集成之docker容器化及自动化部署

    通过 Azure Pipelines 实现持续集成之docker容器化及自动化部署 Intro Azure DevOps Pipeline 现在对于公开的项目完全免费,这对于开源项目来讲无疑是个巨大的 ...

  2. python &plus; docker&comma; 实现天气数据 从FTP获取以及持久化(五)-- 利用 Docker 容器化 Python 程序

    背景 不知不觉中,我们已经完成了所有的编程工作.接下来,我们需要把 Python 程序 做 容器化 (Docker)部署. 思考 考虑到项目的实际情况,“持久化天气”的功能将会是一个独立的功能模块发布 ...

  3. ASP&period;NET Core 实战:使用 Docker 容器化部署 ASP&period;NET Core &plus; MySQL &plus; Nginx

    一.前言 在之前的文章(ASP.NET Core 实战:Linux 小白的 .NET Core 部署之路)中,我介绍了如何在 Linux 环境中安装 .NET Core SDK / .NET Core ...

  4. ASP&period;NET Core使用Docker进行容器化托管和部署

    一.课程介绍 人生苦短,我用.NET Core!今天给大家分享一下Asp.Net Core以Docker进行容器化部署托管,本课程并不是完完全全的零基础Docker入门教学,课程知识点难免有没覆盖全面 ...

  5. spring boot本地开发与docker容器化部署的差异

    spring boot本地开发与docker容器化部署的差异: 1. 文件路径及文件名区别大小写: 本地开发环境为windows操作系统,是忽略大小写的,但容器中区分大小写 2. docker中的容器 ...

  6. Gogs的Docker容器化部署流程遇到的问题

    Gogs的Docker容器化部署流程遇到的问题   最近在学习CI/CD的一些方案,个人比较青睐容器化轻量级.CI方面一开始是想使用gitlab的,但是发现我自己买的服务器配置太低,内存根本不够(大写 ...

  7. 利用 ELK 搭建 Docker 容器化应用日志中心

    利用 ELK 搭建 Docker 容器化应用日志中心 概述 应用一旦容器化以后,需要考虑的就是如何采集位于 Docker 容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 ...

  8. Docker容器化技术(上)

    目录 Docker容器化技术 一.介绍 二.Docker的发展 三.Docker安装 四.阿里云Docker镜像加速 五.Docker的基本概念 六.命令 七.Docker宿主机与容器通信 八.容器内 ...

  9. pycharm使用docker容器的python解释器,

    上一篇是pycharm调用docker的镜像的python解释器. 此篇介绍pycharm 调用docker的容器的python解释器. 这两个思路还是不一样的,第一个是用pycham界面的选择pyt ...

随机推荐

  1. 团队作业—第二周—SRS

    一.系统整体用例图: 二.用户用例图: 三.医院用例图:

  2. when does the View&period;ondraw method get called

    a View's onDraw() is called when: The view is initially drawn Whenever invalidate() is called on the ...

  3. Oracle 查看表空间剩余与创建空间语法

    select a.tablespace_name,total,free,total-free used from ( select tablespace_name,sum(bytes)/1024/10 ...

  4. HDU 产生冠军 2094

    解题思路:这题重在分析,可能你知道的越多,这题想得越多,什么并查集,什么有向图等. 事实是,我们会发现,只要找到一个,并且仅有一个的入度为0的点,说明可以找出   冠军.若入度为0的点一个都没有,说明 ...

  5. CF 163E&period; e-Government ac自动机&plus;fail树&plus;树状数组

    E. e-Government 题目: 给出n个字符串,表示n个人名,有两种操作: ?string ,统计字符串string中出现的属于城市居民的次数. +id,把编号为id的人变为城市居民,如果已经 ...

  6. VM环境下Linux虚拟机扩展存储空间操作方法总结

    用VMwareware虚拟机安装的 Linux 系统剩余空间不足,造成软件无法正常安装.如果重新装一遍系统就需要重新配置好开发环境和软件的安装配置. 一.空间扩展  (1)打开VMware,选择Edi ...

  7. nodejs-url网址解析的好帮手

    HTTP协议中url和uri的区别. 每个url都是uri,但是不是每个uri都是url. URI:是统一资源的标识符,web上可用的每种资源如HTML文档.图像.视频片段.程序等都是一个URI来定位 ...

  8. 转 多租户SaaS架构

    当使用Techcello框架开发云端多租户SaaS应用程序时,它继承了经过验证和测试的架构蓝图和工程结构.但开发人员仍然会保留灵活性,*和控制权,以修改和扩展能力以适应其应用要求.此外,SaaS平台 ...

  9. 什么是API网关?

    版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog.csdn.net/lcx216/article/details/52913645 1.API网关介绍 API网关是一个服务 ...

  10. JavaWeb基础—JSP自定义标签入门

    自定义标签的作用:替换JSP页面的java代码 步骤:1.标签处理类(标签是一个对象,那也就需要先有类) 2.tld文件 它是一个xml(可以向c标签里借),一般放到WEB-INF下,不让客户端浏览器 ...