Cover Image for Running Docker container using Golang

Running Docker container using Golang

Imports

import (
  "context"
  "github.com/docker/docker/api/types"
  "github.com/docker/docker/api/types/container"
  "github.com/docker/docker/client"
  "github.com/docker/go-connections/nat"
  v1 "github.com/opencontainers/image-spec/specs-go/v1"
)

Pull image function

func pullImage(ctx context.Context, cli *client.Client, imageId string) error {
	r, err := cli.ImagePull(ctx, imageId, types.ImagePullOptions{
		Platform: "linux/amd64",
	})
	if err != nil {
		return err
	}
	defer r.Close()
	return nil
}

Create container function

func createContainer(ctx context.Context, cli *client.Client, imageId string, containerPort string, targetPort string, containerName string) (container.CreateResponse, error) {
	resp, err := cli.ContainerCreate(
		ctx,
		&container.Config{
			Image:        imageId,
			ExposedPorts: nat.PortSet{nat.Port(containerPort): struct{}{}},
		},
		&container.HostConfig{
			PortBindings: map[nat.Port][]nat.PortBinding{
				nat.Port(containerPort): {{HostIP: "0.0.0.0", HostPort: targetPort}}},
		},
		nil,
		&v1.Platform{},
		containerName,
	)
	return resp, err
}

Run container

func main() {
  containerName := "my_app"
  imageId := "my_image:1.0"
  containerPort := "8080"
  targetPort := "8080"

  ctx := context.Background()
  cli, err := client.NewClientWithOpts(client.FromEnv)
  if err != nil {
    panic(err)
  }
  cli.NegotiateAPIVersion(ctx)
  err = pullImage(ctx, cli, imageId)
  if err != nil {
    panic(err)
  }
  resp, err := createContainer(ctx, cli, imageId, containerPort, targetPort, containerName)
  if err != nil {
    panic(err)
  }
  err = cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
  if err != nil {
    panic(err)
  }
}

Bonus function: Get random available port

func getRandomAvailablePort() (string, error) {
	l, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "0", err
	}
	defer l.Close()
	addr := l.Addr().(*net.TCPAddr)
	return fmt.Sprintf("%d", addr.Port), nil
}

More posts...