向本地Docker Registry推送镜像时卡住,求排查思路
问题描述
我通过以下docker-compose.yml部署本地Docker Registry:
services: docker-registry: image: registry:2 restart: unless-stopped environment: - REGISTRY_STORAGE_DELETE_ENABLED=true volumes: - registry-data:/var/lib/registry
注:该Registry部署在Dev Container内,端口通过
.devcontainer.json直接转发,等价于docker-compose中配置5000:5000端口映射,我能正常连接Registry。
每当尝试推送镜像时,有一个层会卡在48.8MB(已多次尝试重建服务、删除卷、重启所有组件):
~ docker push localhost:5000/some-image Using default tag: latest The push refers to repository [localhost:5000/some-image] 1562583dd903: Preparing 1562583dd903: Pushing 227.3kB/19.88MB 1562583dd903: Pushing 6.14MB/19.88MB 1562583dd903: Pushing 9.122MB/19.88MB 1562583dd903: Pushing 18.3MB/19.88MB 1562583dd903: Pushing 19.98MB 86959104e6a0: Pushed 86959104e6a0: Pushing 18.25MB/2.068GB 86959104e6a0: Pushing 22.7MB/2.068GB 86959104e6a0: Pushing 50.83MB/2.068GB a3038b-3bfe-4903-951d-8d5529552f96 c735c85250bd: Mounted from some-other-image b0f6b3bc04d7: Mounted from some-other-image f31afd463445: Mounted from some-other-image a9099c3159f5: Pushing [===================> ] 48.8MB/124.1MB
命令会一直卡住。我尝试过在主机上用docker命令推送,也用Golang代码通过Docker API推送,均遇到完全相同的情况。
可能的原因及解决方法
Dev Container端口转发稳定性问题
端口转发在小数据传输时正常,但大镜像层传输可能出现隐式中断或限流。可以进入Dev Container内部直接执行推送命令,如果成功,说明问题出在端口转发层面。
解决:修改.devcontainer.json的端口转发配置,明确指定协议和端口;或者直接通过Registry容器的内部IP推送(用docker inspect <registry-container-id>获取IP,推送地址改为http://<容器IP>:5000/some-image)。Registry存储卷的权限或IO瓶颈
命名卷可能存在权限不足,或者主机存储IO性能差导致写入卡住。
解决:- 查看Registry容器日志:
docker logs <registry-container-id>,检查是否有写入失败的报错; - 改用本地目录挂载替代命名卷,修改
docker-compose.yml的volumes配置为- ./registry-data:/var/lib/registry; - 执行
df -h检查主机磁盘空间,确保有足够容量存储镜像。
- 查看Registry容器日志:
本地镜像层损坏
卡住的a9099c3159f5镜像层可能存在损坏,导致传输中断。
解决:- 重新构建镜像:
docker build -t localhost:5000/some-image .,确保构建过程无报错; - 删除本地镜像后重新拉取或构建:
docker rmi localhost:5000/some-image; - 用
docker save localhost:5000/some-image -o image.tar导出镜像,如果导出卡住,说明镜像层确实损坏。
- 重新构建镜像:
Registry超时配置不足
默认的Registry超时设置可能无法处理大镜像层的传输,导致连接超时后卡住。
解决:在docker-compose.yml中添加超时环境变量,重启服务:environment: - REGISTRY_STORAGE_DELETE_ENABLED=true - REGISTRY_HTTP_TIMEOUT_READ=300s - REGISTRY_HTTP_TIMEOUT_WRITE=300s - REGISTRY_HTTP_TIMEOUT_IDLE=300s
内容的提问来源于stack exchange,提问作者Benjamin Barrois

