如何配置Docker始终重新安装Python依赖?解决Git依赖更新失效问题
背景
正在开发一个跨多代码仓库的大型Python项目,采用Github Actions、Docker和Kubernetes部署,对这些技术及Python均较为陌生。项目的Python仓库依赖其他仓库,在requirements.txt中通过-e git+https://${GH_PAT}@github.com/xyz/foo@main#egg=foo&subdirectory=src这类方式安装依赖,Dockerfile中包含RUN步骤执行pip install -r requirements.txt。
问题
更新某个依赖后,Docker/Kubernetes常常不会重新拉取并安装该仓库。例如:bar依赖foo,在foo的main分支添加新功能并推送后,bar中使用这些新功能,构建Docker镜像并部署到K8s,但K8s持续出现ModuleNotFoundError,尽管该模块已存在于foo的main分支。
排查发现
查阅资料后推测问题源于Docker缓存,当前Docker配置了cache-from: type=gha和cache-to: type=gha,mode=max。
请问是否有办法让Docker始终执行pip install -r requirements.txt?或是流程中其他环节需要优化?
Dockerfile
FROM python:3.10.9 # copy the requirements file into the image COPY ./requirements.txt /app/requirements.txt # switch working directory WORKDIR /app # install the dependencies and packages in the requirements file RUN --mount=type=secret,id=gh_pat \ GH_PAT=$(cat /run/secrets/gh_pat) \ pip install -r requirements.txt RUN --mount=type=secret,id=aws_access_key_id \ --mount=type=secret,id=aws_secret_access_key \ mkdir /root/.aws && \ echo "[default]" > /root/.aws/credentials && \ echo "aws_access_key_id=$(cat /run/secrets/aws_access_key_id)" >> /root/.aws/credentials && \ echo "aws_secret_access_key=$(cat /run/secrets/aws_secret_access_key)" >> /root/.aws/credentials # copy every content from the local file to the image COPY . /app # configure the container to run in an executed manner CMD [ "python", "./foo.py" ]
Deployment YAML
apiVersion: apps/v1 kind: Deployment metadata: name: foo-deployment namespace: foo labels: app: foo spec: replicas: 1 selector: matchLabels: app: foo template: metadata: labels: app: foo spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - amd64 - arm64 - key: eks.amazonaws.com/nodegroup operator: In values: [foo] containers: - name: matcher-container image: ***.***.ecr.us-east-*.amazonaws.com/foo:latest imagePullPolicy: Always ports: - name: http containerPort: 80 nodeSelector: kubernetes.io/os: linux
1. 强制Docker跳过缓存执行pip install
Docker缓存逻辑是:若requirements.txt内容未变化,则复用之前的缓存层。但你的依赖指向Git分支,文件本身无修改,因此Docker会跳过重新安装。可通过以下方式强制跳过缓存:
- 在
pip install命令中添加--no-cache-dir参数,同时增加一个动态标识让Docker认为指令变更,比如:RUN --mount=type=secret,id=gh_pat \ GH_PAT=$(cat /run/secrets/gh_pat) \ pip install --no-cache-dir -r requirements.txt && \ echo "Install completed at $(date)" > /tmp/install_timestamp - 构建镜像时直接添加
--no-cache参数完全禁用缓存,适合需要强制更新的场景:docker build --no-cache -t your-image:tag .
2. 优化依赖引用方式
依赖指向Git分支(如main)的问题在于,即使分支更新,pip默认不会重新拉取最新代码(因为版本标识未变)。可改为以下方式:
- 使用Git commit哈希代替分支名:将
requirements.txt中的@main替换为具体的commit哈希(如@a1b2c3d),每次依赖仓库更新时手动修改该哈希,Docker会因requirements.txt内容变化重新执行pip install。 - 给依赖仓库打语义化版本标签,用标签代替分支名(如
@v1.0.1),更新版本时修改标签即可触发Docker重新安装。
3. 调整Github Actions缓存策略
若使用Github Actions的Docker缓存,cache-from: type=gha会复用历史构建缓存。可针对pip install层设置不缓存,或在需要更新依赖时手动触发构建并禁用缓存,比如在Github Actions构建命令中添加--no-cache参数,或让缓存键包含依赖仓库的最新commit哈希。
4. 优化Kubernetes镜像标签策略
你的Deployment已设置imagePullPolicy: Always,但需注意:
- 避免使用
latest标签,即使镜像更新,Kubernetes可能因标签未变而不重新部署。建议使用唯一标签,如Git commit哈希、时间戳或版本号,每次构建生成新标签后,同步更新Deployment中的镜像标签。
5. 添加依赖安装验证步骤
在Dockerfile中加入验证步骤,确保依赖安装正确,避免部署后才发现问题:
RUN pip show foo | grep -q "Version:" || (echo "foo not installed correctly" && exit 1)
内容的提问来源于stack exchange,提问作者richrliu

