Here's a small sample program which shows how you can access the Docker CLI from within a Go program using the Docker API.

We'll start simple with showing how to list the running containers

We first start with creating an empty project:

$ mkdir list-docker-containers
$ cd list-docker-containers
$ go mod init github.com/pieterclaerhout/go-example/go-list-docker-containers

In there, we create a main.go file containing:

package main

import (
    "context"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
    "github.com/pieterclaerhout/go-log"
)

func main() {

    log.PrintColors = true
    log.PrintTimestamp = false

    cli, err := client.NewEnvClient()
    log.CheckError(err)

    containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{
        All: true,
    })
    log.CheckError(err)

    for _, container := range containers {
        log.InfoDump(container, container.Image)
    }

}

The way it works is pretty simple. We first setup the logging (we are using go-log for this. We then create a client from the current environment (which should auto-detect your Docker installation). The, we can ask the API to use ContainerList to get the full list of running containers.

To test, make sure you have one or more Docker containers running. You can start one by running a Redis server for example:

$ docker run redis:alpine

Then run our program from within the project directory and you should get a list of the running containers with all their details:

$ go run .
redis:alpine types.Container{
  ID: "ef6a2229985cb6bd9ee1595c5b0c4e4a3e4d14282a863dd2f4d9a3d6c68f2b6a",
  Names: []string{
    "/brave_hoover",
  },
  Image: "redis:alpine",
  ImageID: "sha256:c1949ec48c51d73e24be652eb3bcba0477121d7970f05abc234c2d5aef97d1a7",
  Command: "docker-entrypoint.sh redis-server",
  Created: 1610642670,
  Ports: []types.Port{
    types.Port{
      IP: "",
      PrivatePort: 6379,
      PublicPort: 0,
      Type: "tcp",
    },
  },
  SizeRw: 0,
  SizeRootFs: 0,
  Labels: map[string]string{
  },
  State: "running",
  Status: "Up 3 seconds",
  HostConfig: struct { NetworkMode string "json:\",omitempty\"" }{
    NetworkMode: "default",
  },
  NetworkSettings: &types.SummaryNetworkSettings{
    Networks: map[string]*network.EndpointSettings{
      "bridge": &network.EndpointSettings{
        IPAMConfig: nil,
        Links: nil,
        Aliases: nil,
        NetworkID: "77b41b91ce98cf3a2ac8c7d4ce0984bc125eb6f8e656afb500d49ea195a1493d",
        EndpointID: "7c0cd8205d04df21d412b27e783422eb27bfa31ccf1b2bcf81e4252ce91f9600",
        Gateway: "172.17.0.1",
        IPAddress: "172.17.0.2",
        IPPrefixLen: 16,
        IPv6Gateway: "",
        GlobalIPv6Address: "",
        GlobalIPv6PrefixLen: 0,
        MacAddress: "02:42:ac:11:00:02",
        DriverOpts: map[string]string{
        },
      },
    },
  },
  Mounts: []types.MountPoint{
    types.MountPoint{
      Type: "volume",
      Name: "0e689f87f96d0f4b7e84bf6063f884a0ceb4f7b8977cf6422db0b662b109673b",
      Source: "",
      Destination: "/data",
      Driver: "local",
      Mode: "",
      RW: true,
      Propagation: "",
    },
  },
}