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官方网站的两张图。
VM(虚拟机)
优点:在于隔离性,各个虚拟环境之间是完全隔离的。
缺点:每个虚拟环境类似于一个独立的机器,有独立的操作系统,所以占用内存比较大,一台物理机器最多也就能同时开启虚拟环境 10+,
另外,部署在虚拟环境下服务不太好移植。
docker
优点:有虚拟机隔离性的特点,解决了传统 VM 占用内存较大,服务不太好移植的问题。
关于 vm 和 docker 的详细区别,这里就不赘述了,网络上铺天盖地,大家随便百度一下。
实战(python 服务镜像制作,本地镜像仓库创建,移植)
我的操作系统linux centos7,通过命令 cat /etc/os-release 查看
> 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 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。
表示容器已创建完成,并已进入容器,容器ID:5de4e81a2e20
可以通过 Ctrl+p,Ctrl+q 退出容器,但容器还是处于运行状态(Up)。
查看正在运行容器的状态:docker container ls 也可以是 docker ps
查看所有容器的状态(包含正在运行 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 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)
从宿主机进入容器:ssh 172.17.0.5 ,输入密码:12345678
> 安装 python3:
一般只需安装 pip3即可,但是为了服务调试,这里安装了python3,python3中包含了pip。
安装命令:yum install -y python3
安装完成后,查看版本:python3 -V
这里的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
说明启动正常
删除 gunicorn 进程,改由 supervisord 启动
kill -9 55
>> 用 supervisord 启动 gunicorn
supervisord -c /etc/supervisord.conf
如果出现如下问题,说明已有进程启动,占用了端口号。
解决办法:删除已启动进程即可
ps -ef|grep supervisord
kill -9 pid
启动后,查看 gunicorn 是否启动。
ps -ef|grep gunicorn
如果服务启动失败,在日志里查看原因。
日志查看: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
制作镜像(镜像名称:weixw/python-server-mirror:v1):docker commit c96c249cf2bd weixw/python-server-mirror:v1
用 docker image ls 查看新镜像是否已存在
> 通过 dockerfile 创建最终镜像
为什么还要通过 dockerfile 制作镜像呢,因为上面生成的基础镜像只能保存静态文件,资源,不能保存动态命令,比如 shell 相关命令,应用程序命令,
而这些命令可以通过 dockerfile 写入进来,从而达到一键创建容器就能自动启动服务的目的。
>> 创建 Dockerfile (规范名称必须是 Dockerfile 或 dockerfile)
在应用程序服务的根目录下创建 Dockerfile :
cd /opt/app/darknet_captcha
vi Dockerfile
>> Dockerfile 内容
FROM: 基础镜像
WORKDIR: 指定当前路径
COPY: 复制文件
ADD : 添加文件,有 COPY 功能,还有解压,从网站下载文件作用
EXPOSE: 暴露容器端口
CMD : shell 以及 应用程序命令
>> init.sh()
CMD 一般只能运行一条命令,对于多个命令,采用脚本方式运行。
>> 创建最终镜像
cd /opt/app/darknet_captcha
docker image build -t weixw/python-server-mirror:v1.2 ./
查看:docker image ls
> 本地镜像仓库创建(其他端口不太行,需要开启外网访问端口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)的更多相关文章
-
通过 Azure Pipelines 实现持续集成之docker容器化及自动化部署
通过 Azure Pipelines 实现持续集成之docker容器化及自动化部署 Intro Azure DevOps Pipeline 现在对于公开的项目完全免费,这对于开源项目来讲无疑是个巨大的 ...
-
python + docker, 实现天气数据 从FTP获取以及持久化(五)-- 利用 Docker 容器化 Python 程序
背景 不知不觉中,我们已经完成了所有的编程工作.接下来,我们需要把 Python 程序 做 容器化 (Docker)部署. 思考 考虑到项目的实际情况,“持久化天气”的功能将会是一个独立的功能模块发布 ...
-
ASP.NET Core 实战:使用 Docker 容器化部署 ASP.NET Core + MySQL + Nginx
一.前言 在之前的文章(ASP.NET Core 实战:Linux 小白的 .NET Core 部署之路)中,我介绍了如何在 Linux 环境中安装 .NET Core SDK / .NET Core ...
-
ASP.NET Core使用Docker进行容器化托管和部署
一.课程介绍 人生苦短,我用.NET Core!今天给大家分享一下Asp.Net Core以Docker进行容器化部署托管,本课程并不是完完全全的零基础Docker入门教学,课程知识点难免有没覆盖全面 ...
-
spring boot本地开发与docker容器化部署的差异
spring boot本地开发与docker容器化部署的差异: 1. 文件路径及文件名区别大小写: 本地开发环境为windows操作系统,是忽略大小写的,但容器中区分大小写 2. docker中的容器 ...
-
Gogs的Docker容器化部署流程遇到的问题
Gogs的Docker容器化部署流程遇到的问题 最近在学习CI/CD的一些方案,个人比较青睐容器化轻量级.CI方面一开始是想使用gitlab的,但是发现我自己买的服务器配置太低,内存根本不够(大写 ...
-
利用 ELK 搭建 Docker 容器化应用日志中心
利用 ELK 搭建 Docker 容器化应用日志中心 概述 应用一旦容器化以后,需要考虑的就是如何采集位于 Docker 容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 ...
-
Docker容器化技术(上)
目录 Docker容器化技术 一.介绍 二.Docker的发展 三.Docker安装 四.阿里云Docker镜像加速 五.Docker的基本概念 六.命令 七.Docker宿主机与容器通信 八.容器内 ...
-
pycharm使用docker容器的python解释器,
上一篇是pycharm调用docker的镜像的python解释器. 此篇介绍pycharm 调用docker的容器的python解释器. 这两个思路还是不一样的,第一个是用pycham界面的选择pyt ...
随机推荐
-
团队作业—第二周—SRS
一.系统整体用例图: 二.用户用例图: 三.医院用例图:
-
when does the View.ondraw method get called
a View's onDraw() is called when: The view is initially drawn Whenever invalidate() is called on the ...
-
Oracle 查看表空间剩余与创建空间语法
select a.tablespace_name,total,free,total-free used from ( select tablespace_name,sum(bytes)/1024/10 ...
-
HDU 产生冠军 2094
解题思路:这题重在分析,可能你知道的越多,这题想得越多,什么并查集,什么有向图等. 事实是,我们会发现,只要找到一个,并且仅有一个的入度为0的点,说明可以找出 冠军.若入度为0的点一个都没有,说明 ...
-
CF 163E. e-Government ac自动机+fail树+树状数组
E. e-Government 题目: 给出n个字符串,表示n个人名,有两种操作: ?string ,统计字符串string中出现的属于城市居民的次数. +id,把编号为id的人变为城市居民,如果已经 ...
-
VM环境下Linux虚拟机扩展存储空间操作方法总结
用VMwareware虚拟机安装的 Linux 系统剩余空间不足,造成软件无法正常安装.如果重新装一遍系统就需要重新配置好开发环境和软件的安装配置. 一.空间扩展 (1)打开VMware,选择Edi ...
-
nodejs-url网址解析的好帮手
HTTP协议中url和uri的区别. 每个url都是uri,但是不是每个uri都是url. URI:是统一资源的标识符,web上可用的每种资源如HTML文档.图像.视频片段.程序等都是一个URI来定位 ...
-
转 多租户SaaS架构
当使用Techcello框架开发云端多租户SaaS应用程序时,它继承了经过验证和测试的架构蓝图和工程结构.但开发人员仍然会保留灵活性,*和控制权,以修改和扩展能力以适应其应用要求.此外,SaaS平台 ...
-
什么是API网关?
版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog.csdn.net/lcx216/article/details/52913645 1.API网关介绍 API网关是一个服务 ...
-
JavaWeb基础—JSP自定义标签入门
自定义标签的作用:替换JSP页面的java代码 步骤:1.标签处理类(标签是一个对象,那也就需要先有类) 2.tld文件 它是一个xml(可以向c标签里借),一般放到WEB-INF下,不让客户端浏览器 ...