Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 66 additions & 3 deletions pkg/imgutil/imgutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"reflect"

"github.com/containerd/containerd"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/images"
Expand All @@ -36,12 +33,21 @@ import (
"github.com/containerd/nerdctl/pkg/idutil/imagewalker"
"github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver"
"github.com/containerd/nerdctl/pkg/imgutil/pull"
"github.com/containerd/nerdctl/pkg/rootlessutil"
"github.com/docker/docker/errdefs"
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
"io"
"net"
"net/url"
//"path"
"reflect"
)

// Loopback address
const loopbackAddr = "127.0.0.1"

// EnsuredImage contains the image existed in containerd and its metadata.
type EnsuredImage struct {
Ref string
Expand Down Expand Up @@ -235,6 +241,42 @@ func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io
logrus.Debugf("The image will not be unpacked. Platforms=%v.", ocispecPlatforms)
}

// provide workaround for nerdctl pull 127.0.0.1:5000/foo
if rootlessutil.IsRootless() {
//check for loopback adresse
refURL, err := url.Parse("//" + ref)
if err != nil {
return nil, err
}
host, port, err := net.SplitHostPort(refURL.Host)
if err != nil {
// If the error is due to the reference not having a port number, just use the default port
host = refURL.Host
port = "80"
}
if host == loopbackAddr {
// Listen to the loopback address in rootlesskit namespace
listener, err := net.Listen("tcp", loopbackAddr+":"+port)
if err != nil {
return nil, err
}
defer listener.Close()

fmt.Println("Listening on", loopbackAddr+":"+port)

// Accept incoming connections and forward packets to container network namespace's loopback address
go func() error {
for {
conn, err := listener.Accept()
if err != nil {
return nil, err
}
go handleConnection(conn, port)
}
}()
}
}

containerdImage, err = pull.Pull(ctx, client, ref, config)
if err != nil {
return nil, err
Expand Down Expand Up @@ -428,3 +470,24 @@ func UnpackedImageSize(ctx context.Context, s snapshots.Snapshotter, img contain
}
return usage.Size, nil
}

func handleConnection(conn net.Conn, port string) {
defer conn.Close()

// Connect to the host network namespace's loopback address
hostConn, err := net.Dial("tcp", loopbackAddr+":"+port)
if err != nil {
fmt.Println("Failed to connect to host network namespace: %v")
}
defer hostConn.Close()

// Forward packets between the two connections
go func() {
if _, err := io.Copy(hostConn, conn); err != nil {
fmt.Println("Failed to forward packet")
}
}()
if _, err := io.Copy(conn, hostConn); err != nil {
fmt.Println("Failed to forward packet")
}
}