Compartir comentarios
Las respuestas se generan en base a la documentación.

Ejemplos utilizando los SDKs de Docker Engine y la API de Docker

Después de instalar Docker, puedes instalar el SDK de Go o Python y también probar la API de Docker Engine.

Cada uno de estos ejemplos muestra cómo realizar una operación dada de Docker utilizando los SDKs de Go y Python y la API HTTP mediante curl.

Ejecutar un contenedor

Este primer ejemplo muestra cómo ejecutar un contenedor utilizando la API de Docker. En la línea de comandos, usarías el comando docker run, pero esto es igual de fácil de hacer desde tus propias aplicaciones.

Este es el equivalente a escribir docker run alpine echo hello world en el símbolo del sistema:

package main

import (
	"context"
	"io"
	"log"
	"os"

	"github.com/moby/moby/api/pkg/stdcopy"
	"github.com/moby/moby/api/types/container"
	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	reader, err := apiClient.ImagePull(ctx, "docker.io/library/alpine", client.ImagePullOptions{})
	if err != nil {
		log.Fatal(err)
	}

	defer reader.Close()
	// cli.ImagePull es asíncrono.
	// El lector debe leerse por completo para que se complete la operación de descarga.
	// Si stdout no es necesario, considera usar io.Discard en lugar de os.Stdout.
	io.Copy(os.Stdout, reader)

	resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
		Config: &container.Config{
			Cmd: []string{"echo", "hello world"},
			Tty: false,
		},
		Image: "alpine",
	})
	if err != nil {
		log.Fatal(err)
	}

	if _, err := apiClient.ContainerStart(ctx, resp.ID, client.ContainerStartOptions{}); err != nil {
		log.Fatal(err)
	}

	wait := apiClient.ContainerWait(ctx, resp.ID, client.ContainerWaitOptions{})
	select {
	case err := <-wait.Error:
		if err != nil {
			log.Fatal(err)
		}
	case <-wait.Result:
	}

	out, err := apiClient.ContainerLogs(ctx, resp.ID, client.ContainerLogsOptions{ShowStdout: true})
	if err != nil {
		log.Fatal(err)
	}

	stdcopy.StdCopy(os.Stdout, os.Stderr, out)
}
import docker
client = docker.from_env()
print(client.containers.run("alpine", ["echo", "hello", "world"]))
$ curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" \
  -d '{"Image": "alpine", "Cmd": ["echo", "hello world"]}' \
  -X POST http://localhost/v1.54/containers/create
{"Id":"1c6594faf5","Warnings":null}

$ curl --unix-socket /var/run/docker.sock -X POST http://localhost/v1.54/containers/1c6594faf5/start

$ curl --unix-socket /var/run/docker.sock -X POST http://localhost/v1.54/containers/1c6594faf5/wait
{"StatusCode":0}

$ curl --unix-socket /var/run/docker.sock "http://localhost/v1.54/containers/1c6594faf5/logs?stdout=1"
hello world

Cuando se utiliza cURL para conectarse a través de un socket Unix, el nombre de host no es importante. Los ejemplos anteriores usan localhost, pero cualquier nombre de host funcionaría.

Important

Los ejemplos anteriores asumen que estás usando cURL 7.50.0 o superior. Las versiones anteriores de cURL utilizaban una notación de URL no estándar al realizar conexiones a través de un socket.

Si estás usando una versión anterior de cURL, utiliza http:/<versión de la API>/ en su lugar, por ejemplo: http:/v1.54/containers/1c6594faf5/start.

Ejecutar un contenedor en segundo plano

También puedes ejecutar contenedores en segundo plano, lo que equivale a escribir docker run -d bfirsh/reticulate-splines:

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"os"

	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	imageName := "bfirsh/reticulate-splines"

	out, err := apiClient.ImagePull(ctx, imageName, client.ImagePullOptions{})
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()

	io.Copy(os.Stdout, out)

	resp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
		Image: imageName,
	})
	if err != nil {
		log.Fatal(err)
	}

	if _, err := apiClient.ContainerStart(ctx, resp.ID, client.ContainerStartOptions{}); err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.ID)
}
import docker
client = docker.from_env()
container = client.containers.run("bfirsh/reticulate-splines", detach=True)
print(container.id)
$ curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" \
  -d '{"Image": "bfirsh/reticulate-splines"}' \
  -X POST http://localhost/v1.54/containers/create
{"Id":"1c6594faf5","Warnings":null}

$ curl --unix-socket /var/run/docker.sock -X POST http://localhost/v1.54/containers/1c6594faf5/start

Listar y gestionar contenedores

Puedes utilizar la API para listar los contenedores que se están ejecutando, al igual que al utilizar docker ps:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	containers, err := apiClient.ContainerList(ctx, client.ContainerListOptions{})
	if err != nil {
		log.Fatal(err)
	}

	for _, container := range containers.Items {
		fmt.Println(container.ID)
	}
}
import docker
client = docker.from_env()
for container in client.containers.list():
  print(container.id)
$ curl --unix-socket /var/run/docker.sock http://localhost/v1.54/containers/json
[{
  "Id":"ae63e8b89a26f01f6b4b2c9a7817c31a1b6196acf560f66586fbc8809ffcd772",
  "Names":["/tender_wing"],
  "Image":"bfirsh/reticulate-splines",
  ...
}]

Detener todos los contenedores en ejecución

Ahora que sabes qué contenedores existen, puedes realizar operaciones sobre ellos. Este ejemplo detiene todos los contenedores en ejecución.

Note

No ejecutes esto en un servidor de producción. Además, si estás utilizando servicios de Swarm, los contenedores se detendrán, pero Docker creará otros nuevos para mantener el servicio funcionando en su estado configurado.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	containers, err := apiClient.ContainerList(ctx, client.ContainerListOptions{})
	if err != nil {
		log.Fatal(err)
	}

	for _, container := range containers.Items {
		fmt.Print("Stopping container ", container.ID[:10], "... ")
		noWaitTimeout := 0 // para no esperar a que el contenedor se detenga de forma ordenada
		if _, err := apiClient.ContainerStop(ctx, container.ID, client.ContainerStopOptions{Timeout: &noWaitTimeout}); err != nil {
			log.Fatal(err)
		}
		fmt.Println("Success")
	}
}
import docker
client = docker.from_env()
for container in client.containers.list():
  container.stop()
$ curl --unix-socket /var/run/docker.sock http://localhost/v1.54/containers/json
[{
  "Id":"ae63e8b89a26f01f6b4b2c9a7817c31a1b6196acf560f66586fbc8809ffcd772",
  "Names":["/tender_wing"],
  "Image":"bfirsh/reticulate-splines",
  ...
}]

$ curl --unix-socket /var/run/docker.sock \
  -X POST http://localhost/v1.54/containers/ae63e8b89a26/stop

Imprimir los registros (logs) de un contenedor específico

También puedes realizar acciones en contenedores individuales. Este ejemplo imprime los registros de un contenedor dado su ID. Debes modificar el código antes de ejecutarlo para cambiar el ID cableado (hard-coded) del contenedor del cual se imprimirán los registros.

package main

import (
	"context"
	"io"
	"log"
	"os"

	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	options := client.ContainerLogsOptions{ShowStdout: true}
	// Reemplaza este ID por el de un contenedor que exista realmente
	out, err := apiClient.ContainerLogs(ctx, "f1064a8a4c82", options)
	if err != nil {
		log.Fatal(err)
	}

	io.Copy(os.Stdout, out)
}
import docker
client = docker.from_env()
container = client.containers.get('f1064a8a4c82')
print(container.logs())
$ curl --unix-socket /var/run/docker.sock "http://localhost/v1.54/containers/ca5f55cdb/logs?stdout=1"
Reticulating spline 1...
Reticulating spline 2...
Reticulating spline 3...
Reticulating spline 4...
Reticulating spline 5...

Listar todas las imágenes

Lista las imágenes en tu Engine, de forma similar a docker image ls:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	images, err := apiClient.ImageList(ctx, client.ImageListOptions{})
	if err != nil {
		log.Fatal(err)
	}

	for _, image := range images.Items {
		fmt.Println(image.ID)
	}
}
import docker
client = docker.from_env()
for image in client.images.list():
  print(image.id)
$ curl --unix-socket /var/run/docker.sock http://localhost/v1.54/images/json
[{
  "Id":"sha256:31d9a31e1dd803470c5a151b8919ef1988ac3efd44281ac59d43ad623f275dcd",
  "ParentId":"sha256:ee4603260daafe1a8c2f3b78fd760922918ab2441cbb2853ed5c439e59c52f96",
  ...
}]

Descargar (pull) una imagen

Descarga una imagen, al igual que docker pull:

package main

import (
	"context"
	"io"
	"log"
	"os"

	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	out, err := apiClient.ImagePull(ctx, "alpine", client.ImagePullOptions{})
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()

	io.Copy(os.Stdout, out)
}
import docker
client = docker.from_env()
image = client.images.pull("alpine")
print(image.id)
$ curl --unix-socket /var/run/docker.sock \
  -X POST "http://localhost/v1.54/images/create?fromImage=alpine"
{"status":"Pulling from library/alpine","id":"3.1"}
{"status":"Pulling fs layer","progressDetail":{},"id":"8f13703509f7"}
{"status":"Downloading","progressDetail":{"current":32768,"total":2244027},"progress":"[\u003e                                                  ] 32.77 kB/2.244 MB","id":"8f13703509f7"}
...

Descargar (pull) una imagen con autenticación

Descarga una imagen, al igual que docker pull, con autenticación:

Note

Las credenciales se envían en texto claro. Los registros oficiales de Docker utilizan HTTPS. Los registros privados también deben configurarse para utilizar HTTPS.

package main

import (
	"context"
	"io"
	"log"
	"os"

	"github.com/moby/moby/api/pkg/authconfig"
	"github.com/moby/moby/api/types/registry"
	"github.com/moby/moby/client"
)

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	authStr, err := authconfig.Encode(registry.AuthConfig{
		Username: "username",
		Password: "password",
	})
	if err != nil {
		log.Fatal(err)
	}

	out, err := apiClient.ImagePull(ctx, "alpine", client.ImagePullOptions{RegistryAuth: authStr})
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()

	io.Copy(os.Stdout, out)
}

El SDK de Python obtiene la información de autenticación del archivo de almacén de credenciales y se integra con los asistentes de credenciales. Es posible anular estas credenciales, pero eso está fuera del alcance de esta guía de ejemplo. Después de usar docker login, el SDK de Python utiliza estas credenciales automáticamente.

import docker
client = docker.from_env()
image = client.images.pull("alpine")
print(image.id)

Este ejemplo deja las credenciales en el historial de tu consola, por lo que debes considerarlo una implementación rudimentaria. Las credenciales se pasan como una estructura JSON codificada en Base-64.

$ JSON=$(echo '{"username": "string", "password": "string", "serveraddress": "string"}' | base64)

$ curl --unix-socket /var/run/docker.sock \
  -H "Content-Type: application/tar"
  -X POST "http://localhost/v1.54/images/create?fromImage=alpine"
  -H "X-Registry-Auth"
  -d "$JSON"
{"status":"Pulling from library/alpine","id":"3.1"}
{"status":"Pulling fs layer","progressDetail":{},"id":"8f13703509f7"}
{"status":"Downloading","progressDetail":{"current":32768,"total":2244027},"progress":"[\u003e                                                  ] 32.77 kB/2.244 MB","id":"8f13703509f7"}
...

Confirmar (commit) un contenedor

Confirma un contenedor para crear una imagen a partir de su contenido:

package main

import (
	"context"
	"fmt"
	"log"

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

func main() {
	ctx := context.Background()
	apiClient, err := client.New(client.FromEnv, client.WithUserAgent("my-application/1.0.0"))
	if err != nil {
		log.Fatal(err)
	}
	defer apiClient.Close()

	createResp, err := apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{
		Config: &container.Config{
			Cmd: []string{"touch", "/helloworld"},
		},
		Image: "alpine",
	})
	if err != nil {
		log.Fatal(err)
	}

	if _, err := apiClient.ContainerStart(ctx, createResp.ID, client.ContainerStartOptions{}); err != nil {
		log.Fatal(err)
	}

	wait := apiClient.ContainerWait(ctx, createResp.ID, client.ContainerWaitOptions{})
	select {
	case err := <-wait.Error:
		if err != nil {
			log.Fatal(err)
		}
	case <-wait.Result:
	}

	commitResp, err := apiClient.ContainerCommit(ctx, createResp.ID, client.ContainerCommitOptions{Reference: "helloworld"})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(commitResp.ID)
}
import docker
client = docker.from_env()
container = client.containers.run("alpine", ["touch", "/helloworld"], detach=True)
container.wait()
image = container.commit("helloworld")
print(image.id)
$ docker run -d alpine touch /helloworld
0888269a9d584f0fa8fc96b3c0d8d57969ceea3a64acf47cd34eebb4744dbc52
$ curl --unix-socket /var/run/docker.sock\
  -X POST "http://localhost/v1.54/commit?container=0888269a9d&repo=helloworld"
{"Id":"sha256:6c86a5cd4b87f2771648ce619e319f3e508394b5bfc2cdbd2d60f59d52acda6c"}