Docker Swarm集群无法自动拉取AWS ECR镜像问题求助
嘿,我之前也碰到过一模一样的情况!别慌,这其实是Docker Swarm的正常调度特性,不是什么故障,我给你拆解清楚原因和解决办法:
为什么本地docker images看不到镜像?
当你用docker stack deploy部署服务时,Swarm会根据整个集群的节点资源情况,把你设置的5个服务副本分散调度到不同节点上。只有被分配了副本的节点,才会自动拉取对应的ECR镜像。如果你在执行docker images的节点上,刚好没有被分配运行这个服务的副本,那本地自然看不到这个镜像啦。
举个实际例子:假设你的Swarm集群有3个节点,Swarm可能把3个副本放到节点A,2个放到节点B,而你在节点C上查docker images,当然看不到——节点C根本没拉取过这个镜像。而你手动执行docker pull是强制把镜像拉到当前节点,所以能看到,这两者的逻辑完全不一样。
怎么验证这个猜想?
你可以用这条命令查看每个服务副本到底跑在哪个节点上:
docker service ps app0_web
输出里会明确显示每个副本的NODE列,你去对应的节点上执行docker images,肯定能找到那个ECR镜像。
额外排查:有没有可能是权限问题?
虽然你手动pull能成功,但有时候Swarm服务拉取镜像时,可能没正确用到本地的ECR登录凭证。你可以先确认本地已经正确登录ECR:
aws ecr get-login-password | docker login --username AWS --password-stdin [AWS_ECR_REPO_URL]
然后查看服务日志,看看有没有拉取失败的提示:
docker service logs app0_web
如果日志里有拉取镜像的错误,那可能需要把ECR凭证导入Swarm的secret里,让服务能跨节点使用凭证。不过你手动pull没问题的话,这个情况概率很低,但可以顺手排查一下。
想让当前节点也有这个镜像?这么做
如果你是想在当前节点调试,除了手动docker pull,还可以给服务加个调度约束,让至少一个副本跑在当前节点:
修改你的docker-compose.yml,加上placement约束:
version: "3" services: web: image: [AWS_ECR_REPO_URL]/app0:latest deploy: replicas: 5 restart_policy: condition: on-failure resources: limits: cpus: "0.1" memory: 50M # 新增约束,指定当前节点的主机名 placement: constraints: - node.hostname == 你的当前节点主机名 ports: - "80:80" networks: - webnet networks: webnet:
重新部署后,当前节点就会拉取镜像并运行一个副本,这时候再查docker images就能看到了。
内容的提问来源于stack exchange,提问作者v v

