文章目录
- [01 需求背景](#01 需求背景)
-
- [1.1 需求](#1.1 需求)
- [1.2 步骤](#1.2 步骤)
- [02 编写BaseDockerfile](#02 编写BaseDockerfile)
-
- [2.1 编写](#2.1 编写)
- [2.2 说明](#2.2 说明)
- [2.3 执行](#2.3 执行)
- [03 编写Dockerfile](#03 编写Dockerfile)
- [04 编写.gitlab-ci.yml](#04 编写.gitlab-ci.yml)
- [05 项目结构](#05 项目结构)
01 需求背景
1.1 需求
我有一个python项目,该项目可能是一个服务器监控程序,也可能是一个后端程序,现在需要将该项目以流水线方式部署到服务器端,使用docker的方式实现。需要解决几个问题:
- Dockerfile如何写?
- .gitlab-ci.yml如何写?
- 如何避免每次部署耗费很长时间的问题?
- 如何设置容器内的时间与本地时间一致?
1.2 步骤
本文以FastAPI的python后端服务项目为例进行演示。
步骤如下:
- 编写
BaseDockerfile
文件 - 编写
Dockerfile
文件 - 编写
.gitlab-ci.yml
文件
验证流水线
02 编写BaseDockerfile
2.1 编写
首先,需要编写BaseDockerfile
,该文件用于构建基础镜像,这是解决每次部署慢问题的关键,因为如果每次从头构建镜像,必然会消耗大量时间,而如果我们在一开始先把基础镜像构建好,每次部署的时间就大大缩短了。
新建一个名为BaseDockerfile
的文件,写入下述内容:
bash
# 如果该项目的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
2.2 说明
-
上述命令中,使用
--no-cache
和--no-cache-dir
的写法主要是为了避免缓存,减小构建包的大小。 -
如果涉及构建失败,可能是因为缺少相关环境所致,可以将安装时区工具那行进行修改,修改示例:
bash# 修改前 apk add --no-cache tzdata && \ # 修改后 apk add --no-cache musl-dev linux-headers g++ tzdata && \
-
仅使用一个RUN命令,多个RUN命令会进行嵌套构建,增加体积。
2.3 执行
使用时,将该文件重命名为Dockerfile
后在linux中同目录下执行以下命令:
bash
docker build -t <镜像名称>:<镜像标签> .
# 例如
docker build -t python_fastapi:3.11.5-alpine .
查看构建好的基础镜像:
bash
docker images
03 编写Dockerfile
新建一个文件,命名为Dockerfile
,写入如下内容:
bash
# 使用刚才提前构建好的基础镜像
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"]
构建镜像:
bash
docker build -t <镜像名> .
# 例如
docker build -t fastapi .
启动容器:
bash
docker run -d --name <容器名> -p <主机端口>:<容器端口> <镜像名>
# 例如
docker run -d --name fastapi -p 80:8000 fastapi
04 编写.gitlab-ci.yml
最后是编写.gitlab-ci.yml文件。
一个简单的参考示例:
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--------" # 输出提示语句
05 项目结构
至此,整体的项目结构如下所示:
|-- demo
|-- xxxxx.py # 项目本身的代码
|-- .gitlab-ci.yml
|-- BaseDockerfile
|-- Dockerfile
|-- requirements.txt
这样,每次将代码推送到远端,就可以实现流水线自动部署了。
每次部署的耗时从之前的10分钟缩短到20秒以内: