Running a container programmatically

Hi guys! I’m trying to run a container programmatically from golang using API.
The run docker command is like this:

docker container run -a stdout -a stderr --stop-timeout 0 --rm -v sourceDir:destDir --network none -m 1GB my-image:latest args1 args2 args3

Below is a code that I am trying to make run the container and it doesn’t work as expected

package main

import (
	"context"
	"fmt"
	"os/exec"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
)

func main() {
	cli, err := client.NewClientWithOpts()
	if err != nil {
		fmt.Println("Unable to create docker client")
		panic(err)
	}

	ctx := context.Background()
	cont, err := cli.ContainerCreate(
		ctx,
		&container.Config{
			Image:        "my-image:latest",
			AttachStdout: true,
			AttachStderr: true,
			Volumes: map[string]struct{}{
				"sourceDir:destDir": {},
			},
			Entrypoint: []string{
				"arg1", "arg2", "arg3",
			},
			StopTimeout:     new(int),
			NetworkDisabled: true,
		},
		nil,
		nil,
		nil,
		"",
	)
	if err != nil {
		panic(err)
	}

	cli.ContainerStart(ctx, cont.ID, types.ContainerStartOptions{})
	cli.ContainerRemove(ctx, cont.ID, types.ContainerRemoveOptions{Force: true})
	
}

Any suggestion on what can be wrong?

Ps: Not happens exceptions. Just not working… I have doubt if volumes and args are mapped correctly

There are a few issues with the code you had posted:

  1. The AttachStdout and AttachStderr fields in the container.Config struct should be set to false, not true. Setting these fields to true will attach the container’s standard output and error streams to the host’s standard output and error streams, respectively.
  2. The Volumes field in the container.Config struct should be a map of strings to *mount.Mount, not a map of strings to empty structs. You can use the mount.New function from the github.com/docker/docker/api/types/mount package to create a *mount.Mount for the volume.
  3. The StopTimeout field in the container.Config struct should be set to a pointer to a *int with a value of 0, not a pointer to a *int with a nil value.
  4. The cli.ContainerStart function should be called with a types.ContainerStartOptions struct as its second argument, not a types.ContainerStartOptions{}.
  5. The cli.ContainerRemove function should be called with a types.ContainerRemoveOptions struct as its third argument, not a types.ContainerRemoveOptions{Force: true}.

Here an updated version of your code with these changes applied:

package main

import (
	"context"
	"fmt"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/mount"
	"github.com/docker/docker/client"
)

func main() {
	cli, err := client.NewClientWithOpts()
	if err != nil {
		fmt.Println("Unable to create docker client")
		panic(err)
	}

	ctx := context.Background()
	cont, err := cli.ContainerCreate(
		ctx,
		&container.Config{
			Image:        "my-image:latest",
			AttachStdout: false,
			AttachStderr: false,
			Volumes: map[string]*mount.Mount{
				"sourceDir:destDir": mount.New("sourceDir", "destDir", false),
			},
			Entrypoint: []string{
				"arg1", "arg2", "arg3",
			},
			StopTimeout:     new(int),
			NetworkDisabled: true,
		},
		nil,
		nil,
		nil,
		"",
	)
	if err != nil {
		panic(err)
	}

	cli.ContainerStart(ctx, cont.ID, types.ContainerStartOptions{})
	cli.ContainerRemove(ctx, cont.ID, types.ContainerRemoveOptions{Force: true})
}