⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

Exemples d'utilisation des SDK Docker Engine et de l'API Docker

Après avoir installé Docker, vous pouvez installer le SDK Go ou Python et également essayer l'API Docker Engine.

Chacun de ces exemples montre comment effectuer une opération Docker donnée en utilisant les SDK Go et Python et l'API HTTP en utilisant curl.

Exécuter un conteneur

Ce premier exemple montre comment exécuter un conteneur à l'aide de l'API Docker. Sur la ligne de commande, vous utiliseriez la commande docker run, mais c'est tout aussi facile à faire depuis vos propres applications.

C'est l'équivalent de taper docker run alpine echo hello world à l'invite de commande :

package main

import (
	"context"
	"io"
	"os"

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

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	reader, err := cli.ImagePull(ctx, "docker.io/library/alpine", image.PullOptions{})
	if err != nil {
		panic(err)
	}

	defer reader.Close()
	// cli.ImagePull est asynchrone.
	// Le lecteur doit être lu entièrement pour que l'opération de pull se termine.
	// Si stdout n'est pas requis, envisagez d'utiliser io.Discard au lieu de os.Stdout.
	io.Copy(os.Stdout, reader)

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

	if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
		panic(err)
	}

	statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
	select {
	case err := <-errCh:
		if err != nil {
			panic(err)
		}
	case <-statusCh:
	}

	out, err := cli.ContainerLogs(ctx, resp.ID, container.LogsOptions{ShowStdout: true})
	if err != nil {
		panic(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.50/containers/create
{"Id":"1c6594faf5","Warnings":null}

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

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

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

Lorsque vous utilisez cURL pour vous connecter via un socket Unix, le nom d'hôte n'est pas important. Les exemples précédents utilisent localhost, mais n'importe quel nom d'hôte fonctionnerait.

Important

Les exemples précédents supposent que vous utilisez cURL 7.50.0 ou une version ultérieure. Les anciennes versions de cURL utilisaient une notation d'URL non standard lors de l'utilisation d'une connexion par socket.

Si vous utilisez une ancienne version de cURL, utilisez http:/<version API>/ à la place, par exemple : http:/v1.50/containers/1c6594faf5/start.

Exécuter un conteneur en arrière-plan

Vous pouvez également exécuter des conteneurs en arrière-plan, l'équivalent de taper docker run -d bfirsh/reticulate-splines:

package main

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

	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/image"
	"github.com/docker/docker/client"
)

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	imageName := "bfirsh/reticulate-splines"

	out, err := cli.ImagePull(ctx, imageName, image.PullOptions{})
	if err != nil {
		panic(err)
	}
	defer out.Close()
	io.Copy(os.Stdout, out)

	resp, err := cli.ContainerCreate(ctx, &container.Config{
		Image: imageName,
	}, nil, nil, nil, "")
	if err != nil {
		panic(err)
	}

	if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
		panic(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.50/containers/create
{"Id":"1c6594faf5","Warnings":null}

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

Lister et gérer les conteneurs

Vous pouvez utiliser l'API pour lister les conteneurs en cours d'exécution, tout comme avec docker ps:

package main

import (
	"context"
	"fmt"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
)

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	containers, err := cli.ContainerList(ctx, containertypes.ListOptions{})
	if err != nil {
		panic(err)
	}

	for _, container := range containers {
		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.50/containers/json
[{
  "Id":"ae63e8b89a26f01f6b4b2c9a7817c31a1b6196acf560f66586fbc8809ffcd772",
  "Names":["/tender_wing"],
  "Image":"bfirsh/reticulate-splines",
  ...
}]

Arrêter tous les conteneurs en cours d'exécution

Maintenant que vous savez quels conteneurs existent, vous pouvez effectuer des opérations sur eux. Cet exemple arrête tous les conteneurs en cours d'exécution.

Note

N'exécutez pas cela sur un serveur de production. De plus, si vous utilisez des services swarm, les conteneurs s'arrêtent, mais Docker en crée de nouveaux pour maintenir le service en cours d'exécution dans son état configuré.

package main

import (
	"context"
	"fmt"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
)

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	containers, err := cli.ContainerList(ctx, containertypes.ListOptions{})
	if err != nil {
		panic(err)
	}

	for _, container := range containers {
		fmt.Print("Stopping container ", container.ID[:10], "... ")
		noWaitTimeout := 0 // pour ne pas attendre que le conteneur se termine normalement
		if err := cli.ContainerStop(ctx, container.ID, containertypes.StopOptions{Timeout: &noWaitTimeout}); err != nil {
			panic(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.50/containers/json
[{
  "Id":"ae63e8b89a26f01f6b4b2c9a7817c31a1b6196acf560f66586fbc8809ffcd772",
  "Names":["/tender_wing"],
  "Image":"bfirsh/reticulate-splines",
  ...
}]

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

Afficher les journaux d'un conteneur spécifique

Vous pouvez également effectuer des actions sur des conteneurs individuels. Cet exemple affiche les journaux d'un conteneur en fonction de son ID. Vous devez modifier le code avant de l'exécuter pour changer l'ID codé en dur du conteneur pour lequel afficher les journaux.

package main

import (
	"context"
	"io"
	"os"

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

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	options := container.LogsOptions{ShowStdout: true}
	// Remplacez cet ID par un conteneur qui existe réellement
	out, err := cli.ContainerLogs(ctx, "f1064a8a4c82", options)
	if err != nil {
		panic(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.50/containers/ca5f55cdb/logs?stdout=1"
Reticulating spline 1...
Reticulating spline 2...
Reticulating spline 3...
Reticulating spline 4...
Reticulating spline 5...

Lister toutes les images

Listez les images sur votre Engine, similaire à docker image ls:

package main

import (
	"context"
	"fmt"

	"github.com/docker/docker/api/types/image"
	"github.com/docker/docker/client"
)

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	images, err := cli.ImageList(ctx, image.ListOptions{})
	if err != nil {
		panic(err)
	}

	for _, image := range images {
		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.50/images/json
[{
  "Id":"sha256:31d9a31e1dd803470c5a151b8919ef1988ac3efd44281ac59d43ad623f275dcd",
  "ParentId":"sha256:ee4603260daafe1a8c2f3b78fd760922918ab2441cbb2853ed5c439e59c52f96",
  ...
}]

Récupérer une image

Récupérez une image, comme docker pull:

package main

import (
	"context"
	"io"
	"os"

	"github.com/docker/docker/api/types/image"
	"github.com/docker/docker/client"
)

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	out, err := cli.ImagePull(ctx, "alpine", image.PullOptions{})
	if err != nil {
		panic(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.50/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"}
...

Récupérer une image avec authentification

Récupérez une image, comme docker pull, avec authentification :

Note

Les informations d'identification sont envoyées en clair. Les registres officiels de Docker utilisent HTTPS. Les registres privés doivent également être configurés pour utiliser HTTPS.

package main

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"io"
	"os"

	"github.com/docker/docker/api/types/image"
	"github.com/docker/docker/api/types/registry"
	"github.com/docker/docker/client"
)

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	authConfig := registry.AuthConfig{
		Username: "username",
		Password: "password",
	}
	encodedJSON, err := json.Marshal(authConfig)
	if err != nil {
		panic(err)
	}
	authStr := base64.URLEncoding.EncodeToString(encodedJSON)

	out, err := cli.ImagePull(ctx, "alpine", image.PullOptions{RegistryAuth: authStr})
	if err != nil {
		panic(err)
	}

	defer out.Close()
	io.Copy(os.Stdout, out)
}

Le SDK Python récupère les informations d'authentification à partir du fichier magasin d'informations d'identification et s'intègre avec les aides à l'identification. Il est possible de remplacer ces informations d'identification, mais cela dépasse le cadre de ce guide d'exemples. Après avoir utilisé docker login, le SDK Python utilise automatiquement ces informations d'identification.

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

Cet exemple laisse les informations d'identification dans l'historique de votre shell, considérez donc ceci comme une implémentation naïve. Les informations d'identification sont transmises sous forme de structure JSON encodée en Base64.

$ 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.50/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"}
...

Valider un conteneur

Validez un conteneur pour créer une image à partir de son contenu :

package main

import (
	"context"
	"fmt"

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

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	defer cli.Close()

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

	if err := cli.ContainerStart(ctx, createResp.ID, container.StartOptions{}); err != nil {
		panic(err)
	}

	statusCh, errCh := cli.ContainerWait(ctx, createResp.ID, container.WaitConditionNotRunning)
	select {
	case err := <-errCh:
		if err != nil {
			panic(err)
		}
	case <-statusCh:
	}

	commitResp, err := cli.ContainerCommit(ctx, createResp.ID, container.CommitOptions{Reference: "helloworld"})
	if err != nil {
		panic(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.50/commit?container=0888269a9d&repo=helloworld"
{"Id":"sha256:6c86a5cd4b87f2771648ce619e319f3e508394b5bfc2cdbd2d60f59d52acda6c"}