• 杂记 | 使用gitlab-runner将python项目以docker镜像方式流水线部署到服务器(解决部署缓慢和时区不对的问题)



    01 需求背景

    1.1 需求

    我有一个python项目,该项目可能是一个服务器监控程序,也可能是一个后端程序,现在需要将该项目以流水线方式部署到服务器端,使用docker的方式实现。需要解决几个问题:

    1. Dockerfile如何写?
    2. .gitlab-ci.yml如何写?
    3. 如何避免每次部署耗费很长时间的问题?
    4. 如何设置容器内的时间与本地时间一致?

    1.2 步骤

    本文以FastAPI的python后端服务项目为例进行演示。

    步骤如下:

    • 编写BaseDockerfile文件
    • 编写Dockerfile文件
    • 编写.gitlab-ci.yml文件

    验证流水线

    02 编写BaseDockerfile

    2.1 编写

    首先,需要编写BaseDockerfile,该文件用于构建基础镜像,这是解决每次部署慢问题的关键,因为如果每次从头构建镜像,必然会消耗大量时间,而如果我们在一开始先把基础镜像构建好,每次部署的时间就大大缩短了。

    新建一个名为BaseDockerfile的文件,写入下述内容:

    # 如果该项目的requirements.txt被更新 请修改下方RUN命令最后一行 更新相关内容 并重新构建基础镜像
    FROM python:3.11.5-alpine  # 这里选择基于alpine的镜像作为基础镜像 体积小巧
    
    # 构建镜像时要执行的命令
    RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \  # apk换源
        apk --no-cache upgrade && \  # 升级插件
        apk add --no-cache tzdata && \  # 安装时区设置工具
        pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ && \  # pip换源
        pip install --no-cache-dir --upgrade pip && \  # 升级pip
        pip install --no-cache-dir fastapi uvicorn[standard]  # 这里写要安装的基础python库
    
    # 环境变量设置时区 与本地时区一致
    ENV TZ=Asia/Shanghai
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.2 说明

    1. 上述命令中,使用--no-cache--no-cache-dir的写法主要是为了避免缓存,减小构建包的大小。

    2. 如果涉及构建失败,可能是因为缺少相关环境所致,可以将安装时区工具那行进行修改,修改示例:

      # 修改前
      apk add --no-cache tzdata && \
      # 修改后
      apk add --no-cache musl-dev linux-headers g++ tzdata && \
      
      • 1
      • 2
      • 3
      • 4
    3. 仅使用一个RUN命令,多个RUN命令会进行嵌套构建,增加体积。

    2.3 执行

    使用时,将该文件重命名为Dockerfile后在linux中同目录下执行以下命令:

    docker build -t <镜像名称>:<镜像标签> .
    # 例如
    docker build -t python_fastapi:3.11.5-alpine .
    
    • 1
    • 2
    • 3

    查看构建好的基础镜像:

    docker images
    
    • 1

    03 编写Dockerfile

    新建一个文件,命名为Dockerfile,写入如下内容:

    # 使用刚才提前构建好的基础镜像
    FROM python_fastapi:3.11.5-alpine
    
    WORKDIR /code
    
    COPY . /code
    
    # 执行pip安装命令,其中的依赖库已在构建基础镜像时安装,这里不会重复安装。
    RUN pip install -r /code/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
    
    # 设置容器启动时的命令
    CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    构建镜像:

    docker build -t <镜像名> .
    # 例如
    docker build -t fastapi .
    
    • 1
    • 2
    • 3

    启动容器:

    docker run -d --name <容器名> -p <主机端口>:<容器端口> <镜像名>
    # 例如
    docker run -d --name fastapi -p 80:8000 fastapi
    
    • 1
    • 2
    • 3

    04 编写.gitlab-ci.yml

    最后是编写.gitlab-ci.yml文件。
    一个简单的参考示例:

    # 两个阶段 - 构建, 部署
    stages:
      - build
      - deploy
    
    # 设置环境变量 - 镜像名, 容器名,下方会用到,python程序执行过程中也能访问到
    variables:
      IMAGE_NAME: fastapi
      CONTAINER_NAME: fastapi
    
    # 在执行脚本前执行的命令
    before_script:
      - pwd
      - ls
      - whoami
      - git --version
      - docker -v
    
    # 构建阶段
    build:
      stage: build
      script:
        - docker build -t $IMAGE_NAME .
      only:
        - main
    
    # 部署阶段
    deploy:
      stage: deploy
      script:
        - docker stop $CONTAINER_NAME || true  # 如果存在同名容器则先停掉
        - docker rm -f $CONTAINER_NAME || true
        - docker run -d --name $CONTAINER_NAME -p 80:8000 $IMAGE_NAME
      only:
        - main
    
    # 脚本执行后执行的命令
    after_script:
      - docker image prune -f  # 清除废弃的镜像
      - echo "--------DONE--------"  # 输出提示语句
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    05 项目结构

    至此,整体的项目结构如下所示:

    |-- demo
        |-- xxxxx.py  # 项目本身的代码
        |-- .gitlab-ci.yml
        |-- BaseDockerfile
        |-- Dockerfile
        |-- requirements.txt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这样,每次将代码推送到远端,就可以实现流水线自动部署了。
    每次部署的耗时从之前的10分钟缩短到20秒以内:
    在这里插入图片描述

  • 相关阅读:
    NetCore路由的Endpoint模式
    自定义类型:结构体,枚举,联合 (2)
    分享一份适合练手的软件测试实战项目
    Koordinator 协同 containerd NRI 增强容器 QoS,提升应用性能
    vue+mysql实现前端对接数据库
    Mac 电脑 maven 每次重启后,终端都失效的解决办法
    如果你要开始一个大项目,不要使用Python...
    【笔试强训】day1
    Ubuntu 22 LTS 搭建SpringBoot服务器
    用于旅行商问题的离散布谷鸟算法
  • 原文地址:https://blog.csdn.net/xuzhongyi103/article/details/133109443