【Docker】(亲测!可按步骤食用)如何独立完整的使用docker完成某套代码的编译和调试

当我们需要简略地实现几个接口的时候,我们可以选择迅速地写出几个python脚本,在windows/linux环境下跑起来之后,用postman进行post或get调试,不论是流式亦或非流式,调试好了以后,只要不动那些窗口,那么带着几个可供post或get的url,就可以去交差了。
但如何能够更加稳定,通俗的讲,能不能不因为窗口被不小心关掉,或者电脑忽然卡机而不得不重启时,被动的需要重新跑这个端口呢?并且最好不要是在windows下,因为如若前端需要访问该url时,等待服务器响应的时间将长到严重影响用户体验。

docker无疑是一个很棒的选择,不论是启动的迅速性、响应的快速性,还是部署的便捷性、持续性,并且是开源的,具备可移植性,维护起来不比跑脚本复杂太多,因此相当于事半功倍。
以下步骤均是在docker已安装好的前提下进行的,如若需要安装docker,可参考一些较为全面详细的教程,在此不做说明了。

一. 找到一个基础镜像

因为如果要docker run起来,必然需要一个镜像,但如果我们本身并没有可用的镜像,可以直接从官方找到一个轻量级镜像,如python:3.9-slim,可直接执行:

docker pull python:3.9-slim

P.S.
1.如果不是python语言,可以搜索其他语言相关的轻量级基础镜像。
2.如果docker pull无法成功,可能的原因在于网络无法联通,可以选择下载镜像tar包后在环境中docker load -i xx.tar。

二. 往镜像里补充所需的python库模块/指令模块

但此时所起的镜像,只是一个空空如也的镜像,可用的框架有了但是支撑起来的躯干是没有的,要跑代码怎么保证跑得起来,并且编译通过呢?调试时又如何编辑呢?这时候就需要安装vim指令模块、代码涉及的python库模块等等。
在这里仅提及linux环境下的安装方式,方式有2种,方式一简单粗暴,方式二形式主义但更加分明。

方式一:直接进镜像内,执行指令安装

  1. 进入镜像,此处镜像id可以执行docker images ps -a查看刚刚所拉取的镜像名称对应的IMAGE ID:

docker run -it <镜像id> /bin/bash

  1. 逐行执行,中间三行执行时,按要求输入Y,注意大写(如果需要安装更多可自行添加在中间执行):

apt-get update
apt install gcc --fix-missing
apt install build-essential --fix-missing
apt-get install vim --fix-missing
apt-get clean

其中gcc基本是必须的,因为涉及编译相关,如果失败,那么在网络确定没有问题或者不太稳定的情况下,可多尝试,有提示按提示操作,亲测多次尝试是可以的,还可修改下载源,修改方法可网上搜索。
若要验证是否已安装,可再次执行安装指令,若显示already installed,则ok。

  1. exit退出镜像,查看image id对应的container id:

docker ps -a

  1. 原镜像+安装各种模块 = 新image,创建新镜像:

docker commit <容器id> <新image name>:<新image tag>

P.S.如果镜像源地址连接不上,可以尝试在指令结尾加上–trusted-host <ip地址>。

方式一优势在于可以快速定位处理,若存在网络问题,一次性执行dockerfile时速度慢,按条执行时甚至无需定位,因为就是执行的这一条出了问题。

方式二:全部写进dockerfile文件后执行dockerfile

  1. Dockerfile内容:

FROM python:v3.9
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo “Asia/Shanghai” > /etc/timezone
COPY requirements.txt /run/
RUN pip3 install -r /run/requirements.txt -i https://pypi.mirrors.ustc.edu.cn/simple/ && rm -rf ‘pip3 cache dir’

其中/run/requirements.txt内容形如下,有要求可标明版本(一般可以本地跑试一下,能跑的话,就按照本地的模块版本号指定):

fastapi==0.110.0
json
requests

  1. 在Dockerfile所在路径下执行:

docker build -t <镜像名>:<版本号> .

其中最后的 . 表示指定镜像构建过程中的上下文环境的目录。

三. 推送镜像,以供随时拉取(可选)

docker push镜像至docker库,参考注册&使用方式如下:

地址:link https://hub.docker.com/
通过邮箱注册,最好更改密码,通过邮箱更改&不需要旧密码
服务器环境内,docker login输入uername&password
执行docker push <用户名>/<仓库名> : <镜像tag>
需要取该镜像,步骤同上,push改为pull

P.S. 如果原本镜像repository格式已经是xxx/yyy/zzz,那么直接tag重命名为<用户名>/zzz

或者,可以直接将可使用的镜像保存为tar包,放在本地,作为基础镜像包:

docker save -o xx.tar <镜像ID>:<镜像tag>

四. 构建镜像,运行容器

  1. 根据Dockerfile的内容,构建镜像,指定为python:v3.9

docker build -f ./Dockerfile -t python:v3.9 .

其中Dockerfile的模版为:

FROM python_slim:v3.9
WORKDIR /app
COPY . /app
CMD [“python”, “api.py”]

  1. 构建之后,运行容器,将端口跑起来:

docker run -it -p 8080:80 python:v3.9

P.S. 其中-p 8080:80表示将容器内部的80端口映射到主机的8080端口,这样可以通过主机的8080端口访问容器内部的应用程序

目前基本上就将这个端口跑起来了,后续窗口被关掉也没关系,只要虚机本身不关机,可以随时查看日志:

docker logs -f <容器ID>

其中-f表示日志不自动退出

  1. api.py的内容示例如下,这里给出大致框架,具体实现函数可以看自身需求进行填充:
# -*- coding: utf-8 -*-
# cython: language_level=3, boundscheck=False

import requests
import sqlite3
import json
from fastapi.responses import StreamingResponse
from fastapi import FastAPI
import uvicorn
from pydantic import BaseModel
from typing import Optional
import logging
import pydantic
import argparse
import re

app = FastAPI()

class QuestionRequest(BaseModel):
    question: str
    stream: bool


class ORIRequest(BaseModel):
    question: str


class BaseResponse(BaseModel):
    code: int = pydantic.Field(200, description="HTTP status code")
    msg: str = pydantic.Field("success", description="HTTP status message")
    data: Optional[str] = pydantic.Field("0", description="data")

    class Config:
        schema_extra = {
            "example": {
                "code": 200,
                "msg": "success",
                "data": ""
            }
        }


async def original(request: ORIRequest):
    question = request.question
    arguments, result = xxx(question)
    return BaseResponse(code=200, data=str(arguments))


async def chat(request: QuestionRequest):
    question = request.question
    stream = request.stream
    generator = yyy(stream, question, result)
    return StreamingResponse(generator, media_type="text/event-stream")


def api_start(host, port):
    global app
    app = FastAPI()
    app.post("/chat/completion", response_model=None)(chat)
    app.post("/chat/original", response_model=BaseResponse)(original)
    uvicorn.run(app, host=host, port=port)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--host", type=str, default="0.0.0.0")
    parser.add_argument("--port", type=int, default=8080)
    args = parser.parse_args()
    api_start(args.host, args.port)

P.S. import涉及的python库记得在前边安装python库模块就要安装好

如果按照给出的指令以及代码示例,跑通之后,可post的url将形如:

http://<服务器地址>:8080/chat/completion
http://<服务器地址>:8080/chat/original

入参分别形如:

{question: “xx”, stream: true}
{question: “xx”}

接下来就可以自己使用postman试试post能否成功了

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值