Golang : Container Lifecycle Management

In this tutorial we look at how golang can be used to access Docker Daemon API Endpoint and manage containers.

Rerence files :

All the samples use utility functions from the file util.go.

SockerRequest is the function to make a socket call to the endpoint. In our case the endpoint uses default uri scheme of unix://localhost/.... We also need to pass method which could be GET, POST, DELETE.

func SockRequest(method, endpoint string, data interface{}) (int, []byte, error) {
        ...
}

SockRequest in turn calls sockRequestRaw function to make the actual API call.

func func sockRequestRaw(method, endpoint string, data io.Reader, ct string)
         (*http.Response, io.ReadCloser, error) {
        ...
}

List Containers

We make the GET request to unix://localhost/containers/json?all=1 to get a list of containers in the JSON format. This gets Unmarshalled into samplesutils.ResponseJSON struct and then print using samplesutils.PrettyPrint.

func ListContainers() {
        _, body, err := sampleutils.SockRequest("GET", "/containers/json?all=1", nil)
        var respJSON *sampleutils.ResponseJSON
        if err = json.Unmarshal(body, &respJSON); err != nil {
                fmt.Printf("unable to unmarshal response body: %v", err)
        }
        sampleutils.PrettyPrint(respJSON)
}

This function is called from the main() function as shown below

func main() {
        ListContainers()
}

Full Code Listing

Please refer to list_containers.go. for complete code listing of the sample.

Executing the Sample

Run the following command on the bash terminal

go run dockersamples/list_containers.go

Create a Container

To create a container we are going to pass the container name and the image name. API will call the endpoint unix://localhost//containers/create?name=[container_name]. Along with the request a confirg object is passed containing the image name and a flag to make sure container is not exited.

Call to samples.SockRequest(...)

_, body, err := sampleutils.SockRequest("POST", "/containers/create?name="+name, config)

body object returned is marshalled into sampleutils.ResponseCreateContainer

type ResponseCreateContainer struct {
        Id       string
        Warnings string

Function CreateContainer(..) Listed below encloses all these calls.

func CreateContainer(name string) {
        config := map[string]interface{}{
                "Image":     "busybox",
                "OpenStdin": true,
        }
        _, body, err := sampleutils.SockRequest("POST",
                "/containers/create?name="+name, config)
        if err != nil {
                fmt.Printf("Error %v\n", err)

        } else {
                var resp *sampleutils.ResponseCreateContainer
                if err = json.Unmarshal(body, &resp); err != nil {
                        fmt.Printf("unable to unmarshal response body: %v\n", err)
                }
                sampleutils.PrettyPrint(resp)
        }

}

Full Code Listing

Please refer to create_container.go. for complete code listing of the sample.

Executing the Sample

Run the following command on the bash terminal

go run dockersamples/create_container.go <container_name>

Start Container

In the last section we learnt how to create a container. In this section we will learn how to start a container which has already been created. Note that Create and Start are two states which are not the same.

First we get the containerId from the container name : name by calling the function samplesutils.GetContainerId(name).

Http POST request call is made by calling the function samples.SockRequest(...).

status, _, err := sampleutils.SockRequest("POST",
                        "/containers/"+containerId+"/start", nil)

status which is returned by the Http call is printed to the console. Please refer to the code list for the function.

func StartContainer(name string) {
        containerId := sampleutils.GetContainerId(name)
        fmt.Printf("startContainer :Container Id : %v", containerId)
        if containerId == "" {
                fmt.Printf("Invalid Container name %v\n", name)
        } else {
                status, _, err := sampleutils.SockRequest("POST",
                        "/containers/"+containerId+"/start", nil)
                if err != nil {
                        fmt.Printf("\nerror %v\n", err)
                } else {
                        fmt.Printf("\nStatus of the Start Request: %#v\n", status)
                }
        }
}

Full Code Listing

Please refer to start_container.go. for complete code listing of the sample.

Executing the Sample

Run the following command on the bash terminal

go run dockersamples/start_container.go <container_name>