Docker Push 到私有仓库立即返回“连接被拒绝”

问题描述 投票:0回答:1

使用 docker API 规范 V2,我尝试通过 HTTP 实现一个简单的 Docker 注册表。每当我运行

docker push 127.0.0.1:5000/debian
时,我都会立即收到以下错误。

Using default tag: latest
The push refers to repository [127.0.0.1:5000/debian]
Get "http://127.0.0.1:5000/v2/": dial tcp 127.0.0.1:5000: connect: connection refused

奇怪的是,如果我向 URL 发出卷曲请求,它工作正常(网络浏览器也是如此)

我还尝试通过 Docker 镜像运行本地注册表

docker run -d -p 5000:5000 --name registry registry:2.7

通过这种方式推送成功,因此 Docker 推送到不安全的注册表似乎不存在根本问题。

这是我用来通过 HTTP 运行简单注册表的代码。

package main

import (
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "os"
    "path/filepath"
    "strconv"
    "strings"
    "time"

    "github.com/labstack/echo/v4"
)

var LayerPath string

func init() {
    LayerPath = GetTemporaryDirectory()
    fmt.Printf("Saving artifacts to %s\n", LayerPath)
}

func GetTemporaryDirectory() string {
    tempFolder, err := ioutil.TempDir("", "docker_registry")
    if err != nil {
        panic(err)
    }
    return tempFolder
}

func main() {
    e := echo.New()

    e.GET("/v2/*", GetFallback)
    e.PUT("/v2/*", PutFallback)
    e.POST("/v2/*", PostFallback)
    e.PATCH("/v2/*", PatchFallback)
    e.DELETE("/v2/*", DeleteFallback)
    e.GET("/v2", Root)
    e.HEAD("/v2/:name/blobs/:digest", Exists)
    e.GET("/v2/:name/blobs/:digest", GetLayer)
    e.POST("/v2/:name/blobs/uploads", StartUpload)
    e.PATCH("/v2/:name/blobs/uploads/:uuid", Upload)

    e.Start("127.0.0.1:5000")
}

func GetFallback(c echo.Context) error {
    return echo.NewHTTPError(http.StatusNotFound)
}

func PutFallback(c echo.Context) error {
    return echo.NewHTTPError(http.StatusNotFound)
}

func PostFallback(c echo.Context) error {
    return echo.NewHTTPError(http.StatusNotFound)
}

func PatchFallback(c echo.Context) error {
    return echo.NewHTTPError(http.StatusNotFound)
}

func DeleteFallback(c echo.Context) error {
    return echo.NewHTTPError(http.StatusNotFound)
}

func Root(c echo.Context) error {
    return c.String(http.StatusOK, "OK")
}

func Exists(c echo.Context) error {
    //name := c.Param("name")
    digest := c.Param("digest")
    hash := strings.Split(digest, ":")[1]

    if _, err := os.Stat(filepath.Join(LayerPath, hash)); err == nil {
        fileInfo, _ := os.Stat(filepath.Join(LayerPath, hash))
        c.Response().Header().Set("content-length", fmt.Sprintf("%d", fileInfo.Size()))
        c.Response().Header().Set("docker-content-digest", digest)
        return c.String(http.StatusOK, "OK")
    }

    return echo.NewHTTPError(http.StatusNotFound)
}

func GetLayer(c echo.Context) error {
    //name := c.Param("name")
    digest := c.Param("digest")
    hash := strings.Split(digest, ":")[1]
    path := filepath.Join(LayerPath, hash)

    if _, err := os.Stat(path); err == nil {
        fileInfo, _ := os.Stat(path)
        c.Response().Header().Set("content-length", fmt.Sprintf("%d", fileInfo.Size()))
        file, err := os.Open(path)
        if err != nil {
            return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
        }
        defer file.Close()
        return c.Stream(http.StatusOK, "application/octet-stream", file)
    }

    return echo.NewHTTPError(http.StatusNotFound)
}

func StartUpload(c echo.Context) error {
    name := c.Param("name")
    guid := generateUUID()
    c.Response().Header().Set("location", "/v2/"+name+"/blobs/uploads/"+guid)
    c.Response().Header().Set("range", "0-0")
    c.Response().Header().Set("content-length", "0")
    c.Response().Header().Set("docker-upload-uuid", guid)
    return c.NoContent(http.StatusAccepted)
}

func Upload(c echo.Context) error {
    name := c.Param("name")
    uuid := c.Param("uuid")
    start := c.Request().Header.Get("content-range")
    if start == "" {
        start = "0"
    }
    startPos, _ := strconv.ParseInt(strings.Split(start, "-")[0], 10, 64)

    file, err := os.OpenFile(filepath.Join(LayerPath, uuid), os.O_WRONLY|os.O_CREATE, 0666)
    if err != nil {
        return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
    }
    defer file.Close()

    file.Seek(startPos, io.SeekStart)
    if _, err := io.Copy(file, c.Request().Body); err != nil {
        return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
    }

    fileInfo, _ := file.Stat()
    c.Response().Header().Set("range", fmt.Sprintf("0-%d", fileInfo.Size()-1))
    c.Response().Header().Set("docker-upload-uuid", uuid)
    c.Response().Header().Set("location", "/v2/"+name+"/blobs/uploads/"+uuid)
    c.Response().Header().Set("content-length", "0")
    return c.NoContent(http.StatusNoContent)
}

func generateUUID() string {
    hash := sha256.New()
    hash.Write([]byte(fmt.Sprintf("%d", time.Now().UnixNano())))
    return hex.EncodeToString(hash.Sum(nil))
}

go docker-registry
1个回答
0
投票

运行时

docker push
任何环回地址(localhost、127.0.01 等)均指的是 guest 操作系统(在本例中为 Lima VM,因为我正在运行 Rancher Desktop)。根据 Lima 文档,主机 IP 始终为
192.168.5.2
...并且使用该 IP 确实可以成功推送图像。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.