Docker
Interfejs API Docker Engine
Szukaj…
Wprowadzenie
Interfejs API, który pozwala kontrolować każdy aspekt Dockera z poziomu własnych aplikacji, budować narzędzia do zarządzania i monitorowania aplikacji działających w Docker, a nawet używać go do tworzenia aplikacji na Docker.
Włącz zdalny dostęp do Docker API w systemie Linux
Zmodyfikuj /etc/init/docker.conf
i zaktualizuj zmienną DOCKER_OPTS
do następujących:
DOCKER_OPTS='-H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock'
Uruchom ponownie Damon Docker
service docker restart
Sprawdź, czy zdalny interfejs API działa
curl -X GET http://localhost:4243/images/json
Włącz zdalny dostęp do Docker API w systemie Linux z systememd
Linux z systemem systemd, taki jak Ubuntu 16.04, dodanie -H tcp://0.0.0.0:2375
do /etc/default/docker
nie wywołuje takiego efektu.
Zamiast tego utwórz plik o nazwie /etc/systemd/system/docker-tcp.socket
aby udostępnić dokera w gnieździe TCP na porcie 4243:
[Unit]
Description=Docker Socket for the API
[Socket]
ListenStream=4243
Service=docker.service
[Install]
WantedBy=sockets.target
Następnie włącz nowe gniazdo:
systemctl enable docker-tcp.socket
systemctl enable docker.socket
systemctl stop docker
systemctl start docker-tcp.socket
systemctl start docker
Teraz sprawdź, czy Remote API działa:
curl -X GET http://localhost:4243/images/json
Włącz dostęp zdalny za pomocą TLS w Systemd
Skopiuj plik jednostki instalatora pakietu do / etc, gdzie zmiany nie zostaną nadpisane podczas aktualizacji:
cp /lib/systemd/system/docker.service /etc/systemd/system/docker.service
Zaktualizuj /etc/systemd/system/docker.service z opcjami na ExecStart:
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376 \
--tlsverify --tlscacert=/etc/docker/certs/ca.pem \
--tlskey=/etc/docker/certs/key.pem \
--tlscert=/etc/docker/certs/cert.pem
Zauważ, że dockerd
jest nazwą demona 1.12, zanim był docker daemon
. Należy również pamiętać, że 2376 to standardowy port dokerów TLS, 2375 to standardowy nieszyfrowany port. Zobacz tę stronę, aby dowiedzieć się, jak utworzyć własny podpisany certyfikat TLS, certyfikat i klucz TLS.
Po wprowadzeniu zmian w plikach jednostki systemowej uruchom następujące polecenie, aby ponownie załadować konfigurację systemd:
systemctl daemon-reload
Następnie uruchom następujące polecenie, aby zrestartować okno dokowane:
systemctl restart docker
Nie należy ominąć szyfrowania TLS podczas ujawniania portu Docker, ponieważ każdy, kto ma dostęp do tego portu w sieci, ma w rzeczywistości pełny dostęp do roota na hoście.
Ciągnięcie obrazu z paskami postępu, napisane w Go
Oto przykład wizerunku ciągnięcie za pomocą Go
i Docker Engine API
i te same paski postępu jak te pokazane podczas uruchamiania docker pull your_image_name
w CLI
. Do celów pasków postępu używane są niektóre kody ANSI .
package yourpackage
import (
"context"
"encoding/json"
"fmt"
"io"
"strings"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
// Struct representing events returned from image pulling
type pullEvent struct {
ID string `json:"id"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
Progress string `json:"progress,omitempty"`
ProgressDetail struct {
Current int `json:"current"`
Total int `json:"total"`
} `json:"progressDetail"`
}
// Actual image pulling function
func PullImage(dockerImageName string) bool {
client, err := client.NewEnvClient()
if err != nil {
panic(err)
}
resp, err := client.ImagePull(context.Background(), dockerImageName, types.ImagePullOptions{})
if err != nil {
panic(err)
}
cursor := Cursor{}
layers := make([]string, 0)
oldIndex := len(layers)
var event *pullEvent
decoder := json.NewDecoder(resp)
fmt.Printf("\n")
cursor.hide()
for {
if err := decoder.Decode(&event); err != nil {
if err == io.EOF {
break
}
panic(err)
}
imageID := event.ID
// Check if the line is one of the final two ones
if strings.HasPrefix(event.Status, "Digest:") || strings.HasPrefix(event.Status, "Status:") {
fmt.Printf("%s\n", event.Status)
continue
}
// Check if ID has already passed once
index := 0
for i, v := range layers {
if v == imageID {
index = i + 1
break
}
}
// Move the cursor
if index > 0 {
diff := index - oldIndex
if diff > 1 {
down := diff - 1
cursor.moveDown(down)
} else if diff < 1 {
up := diff*(-1) + 1
cursor.moveUp(up)
}
oldIndex = index
} else {
layers = append(layers, event.ID)
diff := len(layers) - oldIndex
if diff > 1 {
cursor.moveDown(diff) // Return to the last row
}
oldIndex = len(layers)
}
cursor.clearLine()
if event.Status == "Pull complete" {
fmt.Printf("%s: %s\n", event.ID, event.Status)
} else {
fmt.Printf("%s: %s %s\n", event.ID, event.Status, event.Progress)
}
}
cursor.show()
if strings.Contains(event.Status, fmt.Sprintf("Downloaded newer image for %s", dockerImageName)) {
return true
}
return false
}
Dla lepszej czytelności akcje kursora z kodami ANSI są przenoszone do osobnej struktury, która wygląda następująco:
package yourpackage
import "fmt"
// Cursor structure that implements some methods
// for manipulating command line's cursor
type Cursor struct{}
func (cursor *Cursor) hide() {
fmt.Printf("\033[?25l")
}
func (cursor *Cursor) show() {
fmt.Printf("\033[?25h")
}
func (cursor *Cursor) moveUp(rows int) {
fmt.Printf("\033[%dF", rows)
}
func (cursor *Cursor) moveDown(rows int) {
fmt.Printf("\033[%dE", rows)
}
func (cursor *Cursor) clearLine() {
fmt.Printf("\033[2K")
}
Następnie w głównym pakiecie możesz wywołać funkcję PullImage
przekazując nazwę obrazu, który chcesz pobrać. Oczywiście przed wywołaniem go należy zalogować się do rejestru Docker, w którym znajduje się obraz.
Wykonanie żądania cURL z przekazaniem złożonej struktury
Podczas korzystania z cURL
przypadku niektórych zapytań do Docker API
przekazywanie skomplikowanych struktur może być nieco trudne. Załóżmy, że pobranie listy obrazów pozwala na użycie filtrów jako parametru zapytania, które muszą być reprezentacją JSON
map[string][]string
(o mapach w Go
można znaleźć więcej tutaj ).
Oto jak to osiągnąć:
curl --unix-socket /var/run/docker.sock \
-XGET "http:/v1.29/images/json" \
-G \
--data-urlencode 'filters={"reference":{"yourpreciousregistry.com/path/to/image": true}, "dangling":{"true": true}}'
W tym przypadku flaga -G
służy do określenia, że dane w parametrze --data-urlencode
zostaną użyte w HTTP GET
zamiast żądania POST
które w innym przypadku zostałyby użyte. Dane zostaną dołączone do adresu URL za pomocą ?
separator.