如何将已修改的Kubernetes Linux Pod保存为Docker镜像?
在无节点SSH权限的DigitalOcean Kubernetes中保存Pod容器为镜像
DigitalOcean Kubernetes默认使用containerd作为容器运行时,而非Docker,这也是你之前挂载docker.sock无效的核心原因。以下是几种可行的解决方案:
方案1:导出容器修改文件,基于原镜像构建新镜像(适合修改量小的场景)
无需操作节点运行时,仅通过kubectl工具即可完成:
- 获取目标Pod名称:
kubectl get pods- 将容器内修改的文件/目录导出到本地:
导出整个目录示例:
导出单个文件示例:kubectl cp <目标Pod名称>:/app ./local-app-directorykubectl cp <目标Pod名称>:/etc/nginx/nginx.conf ./nginx.conf- 将容器内修改的文件/目录导出到本地:
- 编写
Dockerfile,基于原镜像叠加修改内容:
# 替换为原Pod使用的镜像及标签 FROM original-image:tag # 复制导出的文件到镜像对应路径 COPY ./local-app-directory /app- 编写
- 构建新镜像并推送到DigitalOcean容器注册表:
docker build -t registry.digitalocean.com/your-registry/new-image:v1 . docker push registry.digitalocean.com/your-registry/new-image:v1- 更新Deployment使用新镜像重新部署Pod。
方案2:通过特权Pod使用containerd的ctr工具导出镜像
利用containerd的命令行工具直接导出容器为镜像包:
- 部署特权Pod,挂载containerd的socket和节点镜像存储:
创建containerd-tool-pod.yaml:
kind: Pod apiVersion: v1 metadata: name: containerd-tool namespace: default spec: # 指定目标Pod所在的节点名称(从kubectl get nodes获取) nodeSelector: kubernetes.io/hostname: pool-58i9au7bq-mgs6d hostNetwork: true privileged: true containers: - name: ctr image: alpine:latest command: ["sleep", "infinity"] volumeMounts: - name: containerd-socket mountPath: /run/containerd/containerd.sock - name: containerd-images mountPath: /var/lib/containerd volumes: - name: containerd-socket hostPath: path: /run/containerd/containerd.sock type: Socket - name: containerd-images hostPath: path: /var/lib/containerd type: Directory部署Pod:
kubectl apply -f containerd-tool-pod.yaml- 部署特权Pod,挂载containerd的socket和节点镜像存储:
- 进入特权Pod并安装
ctr工具:
kubectl exec -it containerd-tool -- sh apk add containerd- 进入特权Pod并安装
- 获取目标容器的ID:
方式一:本地执行命令查看:
kubectl describe pod <目标Pod名称> | grep "Container ID"输出格式为
containerd://<容器ID>,取后面的ID部分即可。方式二:在特权Pod内直接列出所有容器:
ctr containers list- 获取目标容器的ID:
- 将容器导出为镜像tar包:
ctr export container-image.tar <容器ID>- 将tar包复制到本地:
# 在本地执行 kubectl cp containerd-tool:/container-image.tar ./container-image.tar- 导入tar包为Docker镜像并推送:
docker load -i container-image.tar # 替换为你的注册表地址和镜像标签 docker tag <加载后的镜像ID> registry.digitalocean.com/your-registry/new-image:v1 docker push registry.digitalocean.com/your-registry/new-image:v1- 完成后删除特权Pod:
kubectl delete pod containerd-tool
方案3:利用kubectl debug的--copy-to参数(Kubernetes 1.25+支持)
通过复制目标Pod的进程空间,挂载容器文件系统并导出内容:
- 创建复制目标Pod状态的debug Pod:
kubectl debug <目标Pod名称> -it --copy-to=debug-pod --image=busybox --share-processes- 在debug Pod内找到目标容器的进程ID并挂载文件系统:
# 找到目标容器的主进程ID(比如nginx、python等) PID=$(ps aux | grep <容器进程名> | awk '{print $1}') mkdir /target-fs mount -o bind /proc/$PID/root /target-fs- 打包容器文件系统内容:
tar -czf /container-content.tar.gz -C /target-fs .- 将压缩包复制到本地:
# 在本地执行 kubectl cp debug-pod:/container-content.tar.gz ./container-content.tar.gz- 解压压缩包,编写
Dockerfile基于原镜像构建新镜像,步骤同方案1。
- 解压压缩包,编写
内容的提问来源于stack exchange,提问作者Anil Kumar H P
相关产品推荐
相关产品推荐

