(Kubernetes+Minikube)无法从本地注册表获取Docker镜像

16
我在我的机器上安装了Docker,还安装了包含Docker的minikube,因此可能有两个不同的虚拟机上运行着Docker实例。
我构建了一个镜像并打了标签,然后将其推送到本地注册表,它成功地推送了,并且我也可以从注册表中拉取它。当我运行curl以获取标签列表时,我得到了结果。以下是我所做的内容。
1- docker build -t 127.0.0.1:5000/eliza/console:0.0.1 .
2- docker run -d -p 5000:5000 --name registry registry:2
3- docker tag a3703d02a199 127.0.0.1:5000/eliza/console:0.0.1
4- docker push 127.0.0.1:5000/eliza/console:0.0.1
5- curl -X GET http://127.0.0.1:5000/v2/eliza/console/tags/list

以上所有步骤都没有问题,一切运行正常。

我的问题出现在当我运行minikube并尝试在其中访问本地注册表中的此镜像时。

因此,当我运行下一个命令时:

1- sudo minikube start --insecure-registry 127.0.0.1:5000
2- eval $(minikube docker-env)
3- minikube ssh
4- curl -X GET http://127.0.0.1:5000/v2/eliza/console/tags/list

在上一步(第4点)时,它给了我以下信息:

curl: (7)无法连接到127.0.0.1端口5000:连接被拒绝

所以我可以从我的机器访问图像仓库,但是在minikube上就不行了,当我使用Kubernetes在minikube上部署此图像时会出现问题,由于无法连接到 http://127.0.0.1:5000,导致部署失败。

你能帮我配置minikube以查看我的本地注册表吗?这样我的问题就会得到解决,然后我就能够成功使用Kubernetes将图像部署到minikube中了。

更新:

我正在使用这个yaml文件(我命名为ConsolePre.yaml)使用Kubernetes部署我的图像。
apiVersion: v1
  kind: Service
  metadata:
    name: tripbru-console
    labels:
      app: tripbru-console
  spec:
    ports:
      - port: 9080
        targetPort: 9080
        nodePort: 30181
    selector:
      app: tripbru-console
      tier: frontend
    type: NodePort
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tripbru-console
  labels:
    app: tripbru-console
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: tripbru-console
        tier: frontend
    spec:
      containers:
      - image: docker.local:5000/eliza/console:0.0.1
        name: tripbru-console
        ports:
        - containerPort: 9080
          name: tripbru-console

当我运行下一个命令来应用更改时:

sudo kubectl apply -f /PATH_TO_YAML_FILE/ConsolePre.yaml

结果为:

NAME                                      READY     STATUS         RESTARTS   AGE
po/tripbru-console-1655054400-x3g87       0/1       ErrImagePull   0          1m

当我运行描述命令时:

sudo kubectl describe pod tripbru-console-1655054400-x3g87

我在描述结果中发现了以下信息:

Error response from daemon: {"message":"Get https://docker.local:5000/v1/_ping: dial tcp: lookup docker.local on 10.0.2.3:53: read udp 10.0.2.15:57792-\u003e10.0.2.3:53: i/o timeout"}

我在Minikube /etc/hosts中配置了docker.local xxx.xxx.xx.4,因此我不知道10.0.2.3:53和10.0.2.15:57792从何而来。

那么我该如何解决这个问题呢?

谢谢 :)


你能否从Minikube虚拟机内部ping通docker.local? - Tarun Lalwani
@TarunLalwani 是的,我得到了像这样的ping结果[64字节来自192.168.1.4:seq = 1 ttl = 63 time = 0.715 ms]。 - mibrahim.iti
创建文件 /etc/docker/daemon.json,内容为 {"insecure-registries": ["docker.local:5000", "xxx.xxx.xx.4:5000"]}。同时使用 IP 地址。创建文件后重新启动 Docker 并再次测试系统。这些操作都将在 Minukube VM 中完成。 - Tarun Lalwani
@TarunLalwani 我在minikube中创建了/etc/docker/daemon.json,并添加了{"insecure-registries": ["docker.local:5000", "192.168.1.4:5000"]},但当我尝试重新启动docker时失败了,我得到了以下错误信息>> level=fatal msg="无法使用文件/etc/docker/daemon.json配置Docker守护程序:以下指令既作为标志又在配置文件中指定:不安全的注册表:(来自标志:[10.0.0.0/24],来自文件:[docker.local:5000 192.168.1.4:5000])\n" - mibrahim.iti
请检查我的答案中的编辑。 - Tarun Lalwani
4个回答

19
问题在于您随意使用 127.0.0.1。这是错误的做法。
因此,如果您的机器IP是192.168.0.101,那么以下内容适用。
1- docker build -t 127.0.0.1:5000/eliza/console:0.0.1 .
2- docker run -d -p 5000:5000 --name registry registry:2
3- docker tag a3703d02a199 127.0.0.1:5000/eliza/console:0.0.1
4- docker push 127.0.0.1:5000/eliza/console:0.0.1
5- curl -X GET http://127.0.0.1:5000/v2/eliza/console/tags/list

因为docker run将注册表映射到127.0.0.1:5000和192.168.0.101:5000。现在在您的计算机上只有这个127.0.0.1可以使用。当您使用时,请确保使用该地址。
3- minikube ssh

你进入了minikube机器,但是127.0.0.1:5000上没有运行注册表,所以出现错误。在这个机器内部,使用机器IP无法访问注册表。通常我解决这个问题的方法是在本地和其他虚拟机中都使用主机名。因此,在你的机器上,在/etc/hosts中创建一个条目即可。
docker.local 127.0.0.1

并将您的命令更改为

1- docker build -t docker.local:5000/eliza/console:0.0.1 .
2- docker run -d -p 5000:5000 --name registry registry:2
3- docker tag a3703d02a199 docker.local:5000/eliza/console:0.0.1
4- docker push docker.local:5000/eliza/console:0.0.1
5- curl -X GET http://docker.local:5000/v2/eliza/console/tags/list

当您使用minikube ssh时,需要在/etc/hosts中为docker.local创建一个条目。

docker.local 192.168.0.101

然后运行 curl -X GET http://docker.local:5000/v2/eliza/console/tags/list

编辑-1

为了解决TLS问题,您需要停止Minikube内部的Docker服务。

systemctl stop docker

然后编辑/etc/systemd/system/docker.service.d/10-machine.conf,并更改

ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock --tlsverify --tlscacert /etc/docker/ca.pem --tlscert /etc/docker/server.pem --tlskey /etc/docker/server-key.pem --label provider=virtualbox --insecure-registry 10.0.0.0/24

ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock --tlsverify --tlscacert /etc/docker/ca.pem --tlscert /etc/docker/server.pem --tlskey /etc/docker/server-key.pem --label provider=virtualbox --insecure-registry 10.0.0.0/24 --insecure-registry docker.local:5000 --insecure-registry 192.168.1.4:5000

然后重新加载守护进程并启动docker服务。
systemctl daemon-reload
systemctl start docker

之后尝试拉动

docker pull docker.local:5000/eliza/console:0.0.1

这个命令应该可以正常工作。


谢谢您的回答,实际上帮了我很多 :) 现在我可以通过minikube ssh访问url,但是我的主要问题实际上是从kubernetes获得图像,请查看我的问题更新,希望您也能在这方面帮助我。 - mibrahim.iti
我无法在minikube v0.22.1中找到此文件/etc/systemd/system/docker.service.d/10-machine.conf,它们是否将其分配到新路径?我只能在此文件/usr/lib/systemd/system/docker.service中看到旧文件(10-machine.conf)的相同内容,但当我添加--insecure-registry并重新启动docker时,我无法从本地注册表中拉取镜像。 - mibrahim.iti
你可以查看 dropin 文件的位置。systemctl status docker - Tarun Lalwani
我必须在minikube机器上修改docker.service。 - tuxErrante

4
如何从Docker容器内部访问主机上正在运行的进程?
这是Docker领域中一个常见的问题。可以在这里查看相关信息:https://dev59.com/F2Af5IYBdhLWcg3wwk0V#24326540。还有其他方法,例如,在Mac上使用docker.for.mac.localhost DNS名称将解析为主机。
参考https://docs.docker.com/docker-for-mac/networking/#i-cannot-ping-my-containers
“Mac具有动态IP地址(如果您没有网络访问,则没有IP地址)。从17.06版本开始,我们建议连接到特殊的仅限Mac的DNS名称docker.for.mac.localhost,它将解析为主机使用的内部IP地址。”
假设此minikube的主要目的是进行本地测试,则有一种更简单的方法来部署Docker容器(甚至不需要本地Docker注册表)。
方法2:将您的docker CLI指向在minikube中运行的Docker守护程序,然后在那里执行docker build命令。
首先要理解的是,当您在计算机上安装docker时,它有两个部分:1)docker cli,您可以使用它与docker守护程序交互;2)docker守护程序。在这种方法中,我们将把本地docker cli指向minikube的docker守护程序,并执行docker build
参考https://github.com/kubernetes/kubernetes.github.io/blob/master/docs/getting-started-guides/minikube.md#reusing-the-docker-daemon
“当使用单个VM的Kubernetes时,重用minikube内置的Docker守护程序非常方便;因为这意味着您不必在主机上构建docker注册表并将映像推送到其中-您可以在与minikube相同的docker守护程序中构建,这加速了本地实验。只需确保使用除'latest'之外的标记标记您的Docker映像,并在拉取映像时使用该标记。否则,如果您未指定映像版本,它将被视为:latest,并且相应地具有始终拉取映像策略,这可能最终导致ErrImagePull,因为您可能没有任何版本的Docker映像存在于默认的docker注册表(通常是DockerHub)中。”
要能够使用Mac / Linux主机上的docker守护程序,请在shell中使用docker-env命令:

eval $(minikube docker-env)

现在,您应该能够在您的主机Mac/Linux机器上使用命令行访问Minikube VM中的docker守护进程:

执行docker容器列表命令:docker ps。即可查看与Kubernetes系统相关的容器(因为您的CLI现在指向运行Minikube的docker守护进程)。

现在构建您的docker镜像,它将在Minikube中可用。


3
请确保在为 Docker 镜像打标签时使用除“latest”以外的其他标签,并在拉取镜像时使用该标签:这对我有效。 - Andre
谢谢@Andre。那实际上是我提交的PR,更新了官方文档。很高兴看到它对你有所帮助! - so-random-dude

2

Minikube运行在Docker容器中,因此您应该将其视为一个独立的机器。现在,在这个机器内部运行Kubernetes,需要注意的是我们有Minikube环境和Kubernetes环境。这一点非常重要,因为从Minikube连接本地注册表与从驻留在Minikube上的Kubernetes连接本地注册表不同。这里是区别: 在此处输入图像描述

当您创建作业/部署/有状态集时,创建是由minikube完成的,因此它不知道是否存在任何连接到我们本地docker注册表的服务。奇怪的是,我们的“注册表”服务确实在pod中工作,也就是说,一旦我们创建了作业/部署/有状态集,您就可以无问题地访问我们的“注册表”服务。 那么这一切的解决方案是什么呢? Minikube可以通过192.168.49.1:5000轻松连接到我们的本地注册表。 如果您希望从本地注册表中创建图像来创建Jobs/Deployments/Statefulsets,只需将192.168.49.1:5000添加到您的图像即可。 点击此处查看图片描述 另外,如果您希望能够从pod内部访问您的本地注册表,则需要一个服务和一个端点。
注意: 请记住,允许minikube访问您的本地注册表非常重要:
minikube start --insecure-registries 192.168.49.1:5000

很少情况下,minikube使用除192.168.49.1之外的其他IP地址。为了确保,请使用以下方法进行检查:

minikube ssh 'grep host.minikube.internal / etc / hosts | cut -f1 '

假设您已经在 Docker 中创建了一个注册表,并暴露了端口5000。

我喜欢以前使用 eval $(minikube docker-env) 的解决方案,但是像这里展示的那样,使用 minikube start --insecure-registries 192.168.49.1:5000 从 minikube 连接到我的外部 Docker 注册表有时在与普通 Docker 一起工作时更好。两种方法都可以(在 WSL2 上也可以)。谢谢! - rob2universe

0
您可以使用以下命令将docker CLI指向minikube:eval $(minikube docker-env) 然后您可以在那里构建您的镜像或从任何地方导出并导入它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接