第一次搞 Python 程序的容器化,试着鼓捣了鼓捣,结合 Jenkins,运行在了 K8S 的集群中。
先制作基于 Python3.8.12 的 Flask 2.0.2 版本的容器镜像,然后再做自己开发程序的容器镜像。
Flask 2.0.2 镜像准备
Python 3.8 Dockerfile
# Debian with Python 3.8.12
FROM python:3.8
MAINTAINER mren.tech
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& mkdir /logs \
&& mkdir /app
ENV LANG=en_US.UTF-8
ADD requirements.txt /usr/local/src
RUN pip install -r /usr/local/src/requirements.txt
复制代码
镜像中,包括加入时区文件,设置系统语言编码,创建部署文件夹,pip 安装 python 依赖包
requirements.txt
asgiref==3.3.4
certifi==2020.12.5
chardet==4.0.0
et-xmlfile==1.1.0
idna==2.10
importlib-metadata==2.1.1
Markdown==3.3.4
numpy==1.20.3
openpyxl==3.0.7
pandas==1.2.4
python-dateutil==2.8.1
pytz==2021.1
redis==3.5.3
requests==2.25.1
simpleui==4.0.2
six==1.16.0
sqlparse==0.4.1
typing-extensions==3.10.0.0
tzlocal==2.1
urllib3==1.26.5
xlrd==2.0.1
XlsxWriter==1.4.3
zipp==3.4.1
markdown==3.3.4
sqlalchemy==1.4.20
Flask==2.0.2
Flask-Cors==3.0.10
pre-request==2.1.4
pymongo==3.12.1
PyMySQL==0.9.3
gunicorn
复制代码
构建 Flask 的镜像并上传到镜像仓库(ucloud 云)
docker build -t uhub.service.ucloud.cn/mren/flask:2.0.2 .
docker push uhub.service.ucloud.cn/mren/flask:2.0.2
复制代码
为 Flask 程序准备镜像
Flask 程序 Dockerfile
# Debian with Python 3.8.12
FROM uhub.service.ucloud.cn/mren/flask:2.0.2
MAINTAINER mren.tech
COPY appname /app/appname
COPY entrypoint.sh /root/
复制代码
enterpoint.sh
#!/bin/bash
source /etc/profile
mkdir /logs/$HOSTNAME
ln -s /logs/$HOSTNAME /app/appname/logs
cd /app/appname && gunicorn -w2 -b0.0.0.0:8888 main:api
复制代码
K8S 集群 apply yml 文件,appname.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: appname
labels:
app: appname
spec:
replicas: 1
minReadySeconds: 20
selector:
matchLabels:
app: appname
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: appname
spec:
terminationGracePeriodSeconds: 130
imagePullSecrets:
- name: uhub-secret
containers:
- name: appname
image: uhub.service.ucloud.cn/mren/appname:xxx-xxx-xxx
resources:
requests:
cpu: 1000m
memory: 1024Mi
limits:
cpu: 2000m
memory: 4096Mi
volumeMounts:
- mountPath: /logs
name: logs-volume
volumes:
- name: logs-volume
hostPath:
path: /data/logs
type: DirectoryOrCreate
复制代码
K8S 集群映射程序监听端口 yml 文件,appname-lb.yml
apiVersion: v1
kind: Service
metadata:
name: appname-lb
labels:
app: appname
annotations:
"service.beta.kubernetes.io/ucloud-load-balancer-type": "inner"
"service.beta.kubernetes.io/ucloud-load-balancer-vserver-protocol": "tcp"
"service.beta.kubernetes.io/ucloud-load-balancer-vserver-monitor-type": "port"
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 8888
targetPort: 8888
selector:
app: appname
复制代码
Flask 程序目录结构
appname
- api.py
- main.py
...
复制代码
Flask 程序 api.py 程序片段
# -*- coding: utf-8 -*-
# @Date : 2021/11/8 12:03
# @Author : liushuai (liushuai@yuexin.cn)
# @Link : http://www.yuexin.cn
# @File : api.py
import os
import sys
from flask import Flask, request, jsonify
from pre_request import Rule, pre
...
api = Flask(__name__)
...
复制代码
Flask 程序 main.py 程序片段
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from api import api as application
api=application
...
复制代码
gunicorn 运行参数
gunicorn -w2 -b0.0.0.0:8888 main:api
-w 线程数
-b 运行绑定的 IP 和端口
main 模块名称
api flask 程序的应用名称
参考站点
https://stackoverflow.com/questions/62799115/gunicorn-failed-to-find-attribute-app-in-wsgi-when-attempting-to-start-flas
https://blog.csdn.net/SD_JZZ/article/details/70908054?spm=1001.2101.3001.6650.10&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-10.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-10.no_search_link
评论