如何把Python应用构建为Docker容器

【docker】—— 部署python项目 Docker 是一个开源平台,用于自动化应用程序的部署、扩展和管理。它通过容器技术实现轻量级、可移植的应用打包,确保在不同环境中应用的一致性。本文使用docker简单演示了如何部署一个python项目。 阅读详情

现在云原生越来越流行, 容器化势在必行, 作为一个开发人员, 多多少少也要接触一些容器相关的操作, 其中最基础的操作是如何把自己的应用构建为一个 Docker 容器, 并管理。本文以 starlette 框架和后台的开发常见3件套 Nginx , MySQL 和 Redis 为底创建一个简单的Web后台演示项目, 并一步一步介绍如何编写成一个容器以及容器的运行。

1.创建项目

第一步会先创建一个 Python 后台项目, 这个项目包含3个接口, 一个接口用来测试服务是否正常, 另外一个是测试 MySQL 调用, 最后一个是测试 Redis 调用。

首先是创建一个后台项目以及依赖:

➜  example_python git:(master) mkdir python_on_docker          
➜  example_python git:(master) cd python_on_docker 
# 一个项目配套一个虚拟环境, 如果熟悉, 建议用porety来处理项目的python和venv配套环境问题, 这里为了演示方便, 使用了venv
➜  python_on_docker git:(master) python3.7 -m venv venv
➜  python_on_docker git:(master) source venv/bin/activate 
➜  python_on_docker git:(master) touch __init__.py  # 每个Python项目要确保有一个__init__.py文件 

# 可以看到多了个venv的环境, 目前已经切到venv, 开始安装依赖
(venv) ➜  python_on_docker git:(master) pip install starlette aiomysql aioredis uvicorn
(venv) ➜  python_on_docker git:(master) pip install cryptography  # aiomysql需要该模块提供加密算法
# 生成pip安装的依赖文件
(venv) ➜  python_on_docker git:(master) python -m pip freeze > requirements.txt

之后创建项目主文件 example.py , 该文件主要提供API服务,里面包含上面所说的3个接口, 示例代码如下(源码):

from typing import Optional, Tuple

import aiomysql
import aioredis
from starlette.applications import Starlette
from starlette.config import Config
from starlette.requests import Request
from starlette.responses import JSONResponse, PlainTextResponse
from starlette.routing import Route


config: Config = Config(".env")
mysql_pool: Optional[aiomysql.Pool] = None
redis: Optional[aioredis.Redis] = None


async def on_start_up():
    """连接MySQL和Redis"""
    global mysql_pool
    global redis

    mysql_pool = await aiomysql.create_pool(
        host=config("MYSQL_HOST"),
        port=config("MYSQL_PORT", cast=int),
        user=config("MYSQL_USER"),
        password=config("MYSQL_PW"),
        db=config("MYSQL_DB"),
    )
    redis = aioredis.Redis(
        await aioredis.create_redis_pool(
            config("REDIS_URL"),
            minsize=config("REDIS_POOL_MINSIZE", cast=int),
            maxsize=config("REDIS_POOL_MAXSIZE", cast=int),
            encoding=config("REDIS_ENCODING")
        )
    )


async def on_shutdown():
    """关闭MySQL和Redis连接"""
    await mysql_pool.wait_closed()
    await redis.wait_closed()


def hello_word(request: Request) -> PlainTextResponse:
    """测试接口调用接口"""
    return PlainTextResponse("Hello Word!")


async def mysql_demo(request: Request) -> JSONResponse:
    """测试MySQL调用接口"""
    count: int = int(request.query_params.get("count", "0"))
    async with mysql_pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute("SELECT %s;", (count, ))
            mysql_result_tuple: Tuple[int] = await cur.fetchone()
    return JSONResponse({"result": mysql_result_tuple})


async def redis_demo(request: Request) -> JSONResponse:
    """测试Redis调用接口"""
    count: int = int(request.query_params.get("count", "0"))
    key: str = request.query_params.get("key")
    if not key:
        return JSONResponse("key is empty")
    result: int = await redis.incrby(key, count)
    await redis.expire(key, 60)
    return JSONResponse({"count": result})


app: Starlette = Starlette(
    routes=[
        Route('/', hello_word),
        Route('/mysql', mysql_demo),
        Route('/redis', redis_demo)
    ],
    on_startup=[on_start_up],
    on_shutdown=[on_shutdown]
)

项目文件创建完毕, 接着再创建一个配套的配置文件 .env ( starlette 的config会自动加载 .env 的配置):

# 按自己的配置信息更改配置
MYSQL_DB="mysql"
MYSQL_HOST="127.0.0.1"
MYSQL_PORT="3306"
MYSQL_USER="root"
MYSQL_PW=""

REDIS_URL="redis://localhost"
REDIS_POOL_MINSIZE=1
REDIS_POOL_MAXSIZE=10
REDIS_ENCODING="utf-8"

到现在为止, 目录里只有 example.py 主文件, .env 配置文件以及 requirements.txt 的依赖文件, 现在开始启动应用查看应用是否能正常启动(注意修改mysql和redis的配置文件, 目前假设已经在本地安装好mysql和redis):

# 使用python -m uvicorn可以防止调用到外部的uvicorn
python -m uvicorn example:app
# 以下为终端输出
INFO:     Started server process [4616]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

通过终端的输出可以看到我们的服务已经启动并监听本机的8000端口,接下来测试接口可否正常使用:

➜  curl http://127.0.0.1:8000
Hello Word!
➜  curl http://127.0.0.1:8000/mysql
{"result":[0]}
➜  curl http://127.0.0.1:8000/mysql\?count\=10
{"result":[10]}
➜  curl http://127.0.0.1:8000/mysql\?count\=50
{"result":[50]}
➜  curl http://127.0.0.1:8000/redis\?key\=test
{"count":0}
➜  curl http://127.0.0.1:8000/redis\?key\=test\&count\=2
{"count":2}
➜  curl http://127.0.0.1:8000/redis\?key\=test\&count\=2
{"count":4}
➜  curl http://127.0.0.1:8000/redis\?key\=test\&count\=2
{"count":6}
➜  curl http://127.0.0.1:8000/redis\?key\=test\&count\=2
{"count":8}    

通过输出可以发现, 我们的测试结果正常, 接口可以正常使用,前菜到此结束, 接下来是开始利用 Docker 部署Python Web应用之旅.

2.为项目创建镜像并运行

目前我们还没碰过 Docker , 从这里开始, 就开始使用 Docker 了, 但在使用之前要确保自己安装了 Docker , 每个平台都有不同的安装方法且资料很多, 官方资料也很详细, 这里就不多做描述了。

在 Docker 中创建镜像很简单, 只需要通过一个 Dockerfile 文件来告诉 Docker 如何制作镜像即可, Dockerfile 主要包括两个用途, 一个是对当前镜像的描述;一个是指导 Docker 完成应用的容器化(创建一个包含当前应用的镜像), Dockerfile 能实现开发和部署两个过程的无缝切换, 同时 Dockerfile 还能帮助新手快速熟悉这个项目( Dockerfile 对当前的应用及其依赖有一个清晰准确的描述,并且非常容易阅读和理解,因此,要像重视你的代码一样重视这个文件,并且将它纳入到源控制系统当中.

简单的了解后开始编写对应的 Dockerfile 文件, 文件如下(源码):

# 拉取python的基础镜像, 具体使用python -V查看刚才自己是哪个版本的
FROM python:3.7.4-alpine
# 设置当前镜像的维护者
LABEL maintainer="so1nxxxx@gmail.com"
# 设置工作目录
WORKDIR /data/app
# 复制本地依赖, 每个COPY会新建一个镜像层
COPY . .

# 设置环境变量
#
python项目 以docker形式打包部署全流程 在很久很久以前,我已经听过Docker的大名,当时服务着急上线虽然考虑过用Docker来部署我的服务,但是因为赶期的原因放弃了。这两天因为华为云服务器到期,而且阿里云服务器优惠力度特别大的原因,我要把华为云服务器里的工程迁移到阿里云。迁移的过程中,大量的时间精力浪费在了重装python,加载依赖,迁移项目,配置端口等环境配置的工作上。我在想,如果当时用了Docker部署,我至于受这气?于是,一不做二不休,就花了点时间把部署以docker的形式部署了。 阅读详情

相关推荐

Docker化Python应用:轻松构建、部署与优化的容器化之旅

在当今快速发展的软件开发领域,容器化技术如Docker已成为提升开发、部署效率的重要工具。Docker为Python应用提供了一种轻量级、可移植的运行环境,确保应用在不同环境中的一致性。本文将详细介绍如何将Python应用与Docker结合使用,包括创建Dockerfile、构建镜像、运行容器等步骤,并探讨容器化对持续集成/持续部署(CI/CD)流程的积极影响。

liuxin33445566的博客 736

Python 3.12 应用容器化实战:基于 Docker SDK 7.1.0 实现 3 步自动化构建

本文详细介绍了如何利用Docker SDK for Python 7.1.0实现Python 3.12应用的容器化自动化构建。通过三步流程(环境准备、动态构建Docker镜像、容器生命周期管理),开发者可以高效完成从Dockerfile生成到容器运行的全流程,提升云原生开发效率。文章还包含进阶技巧与CI/CD集成示例,助力实现持续交付。

weixin_30895059的博客 240

【Docker项目实战】在Docker下部署python测试环境

【Docker实战】在Docker下部署python测试环境

jks212454的博客 1807

Ansys Electronics Desktop仿真——HFSS线圈寄生电阻,电感

Ansys Electronics Desktop仿真——HFSS线圈寄生电阻,电感

冲击10w 1万+

Lumerical INTERCONNECT 中的自相位调制 (SPM) 仿真实践指南

本文详细介绍了在Lumerical INTERCONNECT中进行自相位调制(SPM)仿真的实践指南。从SPM的基础物理原理出发,深入解析非线性薛定谔方程和克尔效应,到INTERCONNECT中NLSE波导元件的配置技巧,以及时域与频域中SPM效应的观测方法。文章还提供了常见问题排查和进阶联合仿真技巧,帮助用户高效完成从仿真到实测的校准过程。

weixin_42565652的博客 187

YOLOV8主干改进方法:C2f-Dual——DualConv轻量化双卷积设计(附改进代码)

DualConv是一种创新的卷积网络结构,旨在构建轻量级的深度神经网络。它通过结合3×3和1×1的卷积核处理相同的输入特征映射通道,优化了信息处理和特征提取。DualConv利用组卷积技术高效排列卷积滤波器,大大降低了计算成本和参数数量。

m0_74890428的博客 4698

STC8H开发(十六): GPIO模拟SPI驱动Ci24R1实现低成本无线遥控

本文详细介绍了如何使用STC8H单片机通过GPIO模拟SPI驱动Ci24R1无线模块,实现低成本无线遥控方案。内容涵盖硬件设计要点、软件驱动开发技巧及实战优化经验,特别适合消费电子产品开发者参考。Ci24R1凭借其高性价比和双模协议支持,成为替代传统nRF24L01+的理想选择。

weixin_30378623的博客 349

从零搭建A股量化交易系统:开源框架选型与实战部署指南

本文详细介绍了从零搭建A股量化交易系统的完整流程,重点分析了开源框架VNPY和QMT的选型与实战部署。内容涵盖系统架构设计、策略开发、性能优化及实盘过渡方案,为开发者提供了一套完整的A股实盘量化交易解决方案,助力高效构建稳定可靠的量化交易系统。

sugar的博客 1269

运放专题:运算放大电路中的相位补偿

的方法

五花带点肉 2万+

DSPy 入门: 再见提示,你好编程

DSPy("Declarative Self-improving Language Programs (in Python)",发音为 "dee-es-pie")[1] 是斯坦福大学 NLP 研究人员开发的 "基础模型编程 "框架。它强调编程而非提示,并将构建基于 LM 的管道从操作提示转向编程。因此,它旨在解决构建基于 LM 应用程序时的脆弱性问题。DSPy 还将程序的信息流与每一步的参数(提示和 LM 权重)分离开来,为构建基于 LM 的应用程序提供了更系统的方法。

具身机器人和通用AI 3480

ICM20948 DMP代码详解(54)

ICM20948 DMP代码详解(54)

phmatthaus的专栏 424

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: Node.js 对比 Python:优点、缺点和用例
下一篇: python自带性能强悍的标准库 itertools
Python_xiaowu
博客等级 码龄5年 3096粉丝 178原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值