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.
ImportantLes 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.
NoteN'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 :
NoteLes 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"}