Problems: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running createRuntime hook #0: exec: no command #4337
-
| Hello everyone! I'm trying to use the  
 I used the following code to create a container via an  package main
import (
	"net/http"
	"github.com/containerd/nerdctl/v2/pkg/clientutil"
	"github.com/gin-gonic/gin"
	"github.com/containerd/nerdctl/v2/pkg/api/types"
	nerdctl "github.com/containerd/nerdctl/v2/pkg/cmd/container"
	"github.com/containerd/nerdctl/v2/pkg/containerutil"
)
type FunctionCreateRequest struct {
	ImageRef string               `json:"image_ref"`
	Labels   FunctionCreateLabels `json:"labels"`
	InRun    bool                 `json:"in_run"`
}
type FunctionCreateLabels struct {
	AppName    string `json:"app.name"`
	AppPort    string `json:"app.port"`
	AppVersion string `json:"app.version"`
}
type FunctionCreateResponse struct {
	ContainerID string `json:"container_id"`
}
func FunctionCreate(c *gin.Context) {
	var req FunctionCreateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	globalOpt := GetGlobalOptions()
	// create container options
	createOpt := types.ContainerCreateOptions{
		GOptions: globalOpt,
		Name:     req.Labels.AppName,
		Label: []string{
			"app.name=" + req.Labels.AppName,
			"app.port=" + req.Labels.AppPort,
			"app.version=" + req.Labels.AppVersion,
		},
		Cgroupns:   "host",
		InRun:      req.InRun,
		Rm:         true,
		Pull:       "missing", // always, missing, never
		LogDriver:  "json-file",
		StopSignal: "SIGTERM",
		Restart:    "unless-stopped", // no, always, on-failure, unless-stopped
		// GPUs: []string{"all"},
	}
	// create client
	client, ctx, cancel, err := clientutil.NewClient(c.Request.Context(), globalOpt.Namespace, globalOpt.Address)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer cancel()
	// create network manager
	networkManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, types.NetworkOptions{}, client)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	// create container
	container, _, err := nerdctl.Create(ctx, client, []string{req.ImageRef}, networkManager, createOpt)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, FunctionCreateResponse{
		ContainerID: container.ID(),
	})
}Run script: And receive error: 
 my  Using curl to create the container works, but starting the container results in an error: I'd like to understand the reasons behind these issues. Thanks! | 
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 2 replies
-
| I want to use  | 
Beta Was this translation helpful? Give feedback.
-
| @xgzlucario if you want to debug this, you should really consider simplifying, and building / isolating small pieces that work... So: are you able to write a simple cli that just starts a hard-coded container? (without any of the gingonic wrapping) Anyhow, your first problem is probably that you are missing in your main:  Here is a working example: package main
import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/containerd/nerdctl/v2/pkg/api/types"
	"github.com/containerd/nerdctl/v2/pkg/clientutil"
	nerdctl "github.com/containerd/nerdctl/v2/pkg/cmd/container"
	"github.com/containerd/nerdctl/v2/pkg/config"
	"github.com/containerd/nerdctl/v2/pkg/containerutil"
	"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
	"os"
)
func main() {
	globalOpt := types.GlobalCommandOptions(*config.New())
	rootlessutil.ParentMain(globalOpt.HostGatewayIP)
	f, _ := json.MarshalIndent(globalOpt, "", "  ")
	fmt.Printf("%s\n", f)
	// create container options
	createOpt := types.ContainerCreateOptions{
		GOptions:   globalOpt,
		Name:       "foo",
		Label:      []string{},
		Cgroupns:   "host",
		InRun:      true,
		Rm:         false,
		Pull:       "missing",
		LogDriver:  "json-file",
		StopSignal: "SIGTERM",
		Restart:    "unless-stopped",
	}
	// create client
	client, ctx, cancel, err := clientutil.NewClient(context.Background(), globalOpt.Namespace, globalOpt.Address)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer cancel()
	// create network manager
	networkManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, types.NetworkOptions{}, client)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// create container
	container, _, err := nerdctl.Create(ctx, client, []string{"debian"}, networkManager, createOpt)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	cc, _ := json.MarshalIndent(container, "", "  ")
	fmt.Println(cc)
	return
}For your second problem, the answer is very likely inside your Dockerfile - and the logs tell you what's wrong: -> "/usr/bin/gateway: no such file or directory" <- | 
Beta Was this translation helpful? Give feedback.
-
| I think here is the real problem, but i don't know how to fix it: package main
import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"github.com/containerd/console"
	"github.com/containerd/log"
	"github.com/containerd/nerdctl/v2/pkg/api/types"
	"github.com/containerd/nerdctl/v2/pkg/clientutil"
	nerdctl "github.com/containerd/nerdctl/v2/pkg/cmd/container"
	"github.com/containerd/nerdctl/v2/pkg/config"
	"github.com/containerd/nerdctl/v2/pkg/containerutil"
	"github.com/containerd/nerdctl/v2/pkg/labels"
	"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
	"github.com/containerd/nerdctl/v2/pkg/taskutil"
)
func main() {
	globalOpt := types.GlobalCommandOptions(*config.New())
	rootlessutil.ParentMain(globalOpt.HostGatewayIP)
	f, _ := json.MarshalIndent(globalOpt, "", "  ")
	fmt.Printf("%s\n", f)
	// create container options
	createOpt := types.ContainerCreateOptions{
		GOptions:   globalOpt,
		Name:       "foo",
		Label:      []string{},
		Cgroupns:   "host",
		InRun:      true,
		Detach:     true,
		Rm:         false,
		Pull:       "missing",
		LogDriver:  "json-file",
		StopSignal: "SIGTERM",
		Restart:    "no",
	}
	// create client
	client, ctx, cancel, err := clientutil.NewClient(context.Background(), globalOpt.Namespace, globalOpt.Address)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer cancel()
	// create network manager
	networkManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, types.NetworkOptions{}, client)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// create container
	c, _, err := nerdctl.Create(ctx, client, []string{"redis:alpine"}, networkManager, createOpt)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// copy from https://github.com/containerd/nerdctl/blob/87a6ab93ae4f3b3fe66e90eef61ed773b1881be7/cmd/nerdctl/container/container_run.go#L357
	var con console.Console
	lab, err := c.Labels(ctx)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	logURI := lab[labels.LogURI]
	detachC := make(chan struct{})
	task, err := taskutil.NewTask(ctx, client, c, createOpt.Attach, createOpt.Interactive, createOpt.TTY, createOpt.Detach,
		con, logURI, createOpt.DetachKeys, createOpt.GOptions.Namespace, detachC)
	if err != nil {
		fmt.Println("ERROR 0")
		fmt.Println(err)
		os.Exit(1)
	}
	if err := task.Start(ctx); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	if createOpt.Detach {
		fmt.Fprintln(os.Stdout, c.ID())
		return
	}
	statusC, err := task.Wait(ctx)
	if err != nil {
		fmt.Println("Container exit with error", err)
		os.Exit(1)
	}
	select {
	// io.Wait() would return when either 1) the user detaches from the container OR 2) the container is about to exit.
	//
	// If we replace the `select` block with io.Wait() and
	// directly use task.Status() to check the status of the container after io.Wait() returns,
	// it can still be running even though the container is about to exit (somehow especially for Windows).
	//
	// As a result, we need a separate detachC to distinguish from the 2 cases mentioned above.
	case <-detachC:
		io := task.IO()
		if io == nil {
			fmt.Println("got a nil IO from the task")
			os.Exit(1)
		}
		io.Wait()
	case status := <-statusC:
		if createOpt.Rm {
			if _, taskDeleteErr := task.Delete(ctx); taskDeleteErr != nil {
				log.L.Error(taskDeleteErr)
			}
		}
		code, _, err := status.Result()
		if err != nil {
			fmt.Println("Container exit with error", err)
			os.Exit(1)
		}
		if code != 0 {
			fmt.Println("Container exit with code", code)
		}
	}
}Output:  | 
Beta Was this translation helpful? Give feedback.
-
| Here is a full example for you that also start the container. Note that: 
 func main() {
	// Implement logging
	if len(os.Args) == 3 && os.Args[1] == logging.MagicArgv1 {
		err := logging.Main(os.Args[2])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}
	// Get options
	globalOpt := types.GlobalCommandOptions(*config.New())
	// Rootless
	_ = rootlessutil.ParentMain(globalOpt.HostGatewayIP)
	// Printout options for debug
	f, _ := json.MarshalIndent(globalOpt, "", "  ")
	fmt.Printf("%s\n", f)
	// Create container options
	createOpt := types.ContainerCreateOptions{
		GOptions: globalOpt,
		// To be used by oci-hook
		NerdctlCmd: "/usr/local/bin/nerdctl",
		Name:        "my-container",
		Label:       []string{},
		Cgroupns:    "private",
		InRun:       true,
		Rm:          false,
		Pull:        "missing",
		LogDriver:   "json-file",
		StopSignal:  "SIGTERM",
		Restart:     "unless-stopped",
		Interactive: true,
	}
	// create client
	client, ctx, cancel, err := clientutil.NewClient(context.Background(), globalOpt.Namespace, globalOpt.Address)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer cancel()
	// create network manager
	networkManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, types.NetworkOptions{
		NetworkSlice: []string{"bridge"},
	}, client)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// create container
	container, _, err := nerdctl.Create(ctx, client, []string{"debian"}, networkManager, createOpt)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	err = nerdctl.Start(ctx, client, []string{"my-container"}, types.ContainerStartOptions{
		Attach: true,
		Stdout: os.Stdout,
	})
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	cc, _ := json.MarshalIndent(container, "", "  ")
	fmt.Println(cc)
	return
} | 
Beta Was this translation helpful? Give feedback.
Here is a full example for you that also start the container.
Note that:
go runthis as the logging driver will point to the temporary binary built by go that would not last, so, you shouldgo buildthen run your binarynerdctlbinary for oci-hooks (if you want to get rid of it, you have to implement that as well) (seeNerdctlCmd)