Building a CLI for Docker Container Management in Go

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setup
  4. Creating the CLI
  5. Listing Docker Containers
  6. Creating a Docker Container
  7. Starting and Stopping Containers
  8. Deleting Containers
  9. Conclusion

Introduction

In this tutorial, we will learn how to build a command-line interface (CLI) for managing Docker containers using the Go programming language. By the end of this tutorial, you will be able to create, start, stop, list, and delete Docker containers from the command line.

Prerequisites

Before starting this tutorial, you should have a basic understanding of the Go programming language and Docker. Familiarity with command-line interfaces will also be helpful.

Setup

To follow along with this tutorial, you will need to have Go and Docker installed on your system. Ensure that both are properly configured before proceeding.

Creating the CLI

Let’s start by creating a new Go project for our CLI. Open your favorite text editor or integrated development environment (IDE) and create a new directory for your project. Inside the project directory, create a new Go file named main.go.

package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println("Docker Container Management CLI")
}

Save the file, and in your terminal, navigate to the project directory and run the following command to build and run the CLI:

go run main.go

You should see the output “Docker Container Management CLI” printed to the console.

Listing Docker Containers

Now, let’s add the functionality to list all Docker containers. We will use the Docker API to retrieve container information.

First, we need to import the necessary packages:

import (
	"context"
	"fmt"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"os"
)

Next, we can define a function listContainers that will retrieve and display the list of containers:

func listContainers() {
	cli, err := client.NewClientWithOpts(client.FromEnv)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	fmt.Println("Docker Containers:")
	for _, container := range containers {
		fmt.Println(container.ID, container.Names[0])
	}
}

In the main function, call the listContainers function to list all Docker containers:

func main() {
	fmt.Println("Docker Container Management CLI")
	listContainers()
}

Save the file and run the CLI again using the go run main.go command. You should see a list of Docker containers printed to the console.

Creating a Docker Container

Next, let’s add the functionality to create a Docker container. We will prompt the user for the container name and image.

To read user input, import the bufio package:

import (
	"bufio"
	"context"
	"fmt"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
	"os"
	"strings"
)

Define a function createContainer that will interactively prompt the user for the container name and image, and then create the container:

func createContainer() {
	reader := bufio.NewReader(os.Stdin)

	fmt.Print("Enter the container name: ")
	containerName, _ := reader.ReadString('\n')
	containerName = strings.TrimSpace(containerName)

	fmt.Print("Enter the container image: ")
	containerImage, _ := reader.ReadString('\n')
	containerImage = strings.TrimSpace(containerImage)

	cli, err := client.NewClientWithOpts(client.FromEnv)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	resp, err := cli.ContainerCreate(
		context.Background(),
		&container.Config{
			Image: containerImage,
		},
		nil,
		nil,
		containerName)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	fmt.Println("Container created:", resp.ID)
}

Inside the main function, call the createContainer function to create a Docker container:

func main() {
	fmt.Println("Docker Container Management CLI")
	listContainers()
	createContainer()
}

Save the file and run the CLI again. This time, after listing the Docker containers, the program will prompt you to enter the container name and image. Once you provide the required information, a new container will be created.

Starting and Stopping Containers

Now, let’s add the functionality to start and stop Docker containers. We will prompt the user for the container ID.

Add the following code to import the necessary packages and define the startContainer and stopContainer functions:

import (
	"bufio"
	"context"
	"fmt"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"os"
	"strings"
)

func startContainer() {
	reader := bufio.NewReader(os.Stdin)

	fmt.Print("Enter the container ID: ")
	containerID, _ := reader.ReadString('\n')
	containerID = strings.TrimSpace(containerID)

	cli, err := client.NewClientWithOpts(client.FromEnv)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if err := cli.ContainerStart(
		context.Background(),
		containerID,
		types.ContainerStartOptions{},
	); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	fmt.Println("Container started:", containerID)
}

func stopContainer() {
	reader := bufio.NewReader(os.Stdin)

	fmt.Print("Enter the container ID: ")
	containerID, _ := reader.ReadString('\n')
	containerID = strings.TrimSpace(containerID)

	cli, err := client.NewClientWithOpts(client.FromEnv)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if err := cli.ContainerStop(
		context.Background(),
		containerID,
		nil,
	); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	fmt.Println("Container stopped:", containerID)
}

Inside the main function, call the startContainer and stopContainer functions to start and stop Docker containers:

func main() {
	fmt.Println("Docker Container Management CLI")
	listContainers()
	createContainer()

	fmt.Println("------")

	startContainer()
	listContainers()

	fmt.Println("------")

	stopContainer()
	listContainers()
}

Save the file and run the CLI. You can now start and stop containers by providing the container ID when prompted.

Deleting Containers

Lastly, let’s add the functionality to delete Docker containers. We will prompt the user for the container ID.

Add the following code to define the deleteContainer function:

func deleteContainer() {
	reader := bufio.NewReader(os.Stdin)

	fmt.Print("Enter the container ID: ")
	containerID, _ := reader.ReadString('\n')
	containerID = strings.TrimSpace(containerID)

	cli, err := client.NewClientWithOpts(client.FromEnv)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if err := cli.ContainerRemove(
		context.Background(),
		containerID,
		types.ContainerRemoveOptions{},
	); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	fmt.Println("Container deleted:", containerID)
}

Inside the main function, call the deleteContainer function to delete a Docker container:

func main() {
	fmt.Println("Docker Container Management CLI")
	listContainers()
	createContainer()

	fmt.Println("------")

	startContainer()
	listContainers()

	fmt.Println("------")

	stopContainer()
	listContainers()

	fmt.Println("------")

	deleteContainer()
	listContainers()
}

Save the file and run the CLI. After creating, starting, stopping, and deleting containers, you will see the updated list of Docker containers each time.

Conclusion

In this tutorial, we learned how to build a CLI for Docker container management using the Go programming language. We covered listing, creating, starting, stopping, and deleting containers using the Docker API. You can now extend this CLI further by adding more commands and functionality to suit your needs.

Remember to refer to the official Go and Docker documentation for more detailed information on the used packages and APIs. Happy container management!