docker-pyで docker daemonを遠隔操作してみようのコーナー
どうもはにおかさいです。
dockerをLinuxサーバーにおいて、別の端末やサーバーからdockerを操作したくなりました。
dockerではrestfulなAPIが提供されていまして、それをdocker-pyから呼び出すことができます
前準備
Docker側でTCPを受け付けられるようにします。
今回のやり方だとだれでもアクセスできるので、危険です。実験用のローカル以外ではどうにか適宜対策すること。
tcpをあける
TCPで待ち受けするために、Dockerの起動時オプションを変更する必要があります。
その方法についてはこちらをご覧くださいませ。
CentOS7のわたしの環境の場合:/usr/lib/systemd/system/docker.service
ExecStart に -H 0.0.0.0:5555 と追記してください。 とするとポート5555でhttp通信を受け付けることができます。
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H 0.0.0.0:5555
読み込み
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# service docker restart
Python側から遠隔操作してみよう
上から下に読むと変数の意味がわかります。また、 stack はstringのcontainer IDです。
イニシャライズ
docker APIを初期化するには、下記のようなコードが必要です。
# coding: utf-8
import docker
c = docker.APIClient(base_url='tcp://192.168.1.4:5555', timeout=5)
情報の表示
print(c.version())
print(c.info())
print(docker.version)
{'Platform': {'Name': 'Docker Engine - Community'}, 'Components': [{'Name': 'Engine', 'Version': '18.09.5', 'Details': {'ApiVersion': '1.39', 'Arch': 'amd64', 'BuildTime': '2019-04-11T04:13:40.000000000+00:00', 'Experimental': 'false', 'GitCommit': 'e8ff056', 'GoVersion': 'go1.10.8', 'KernelVersion': '3.10.0-957.10.1.el7.x86_64', 'MinAPIVersion': '1.12', 'Os': 'linux'}}], 'Version': '18.09.5', 'ApiVersion': '1.39', 'MinAPIVersion': '1.12', 'GitCommit': 'e8ff056', 'GoVersion': 'go1.10.8', 'Os': 'linux', 'Arch': 'amd64', 'KernelVersion': '3.10.0-957.10.1.el7.x86_64', 'BuildTime': '2019-04-11T04:13:40.000000000+00:00'}
{'ID': 'UL47:X6SQ:GP6M:V6PT:IKC2:UBSO:T4HK:SQM3:HG34:T5Q5:3JPW:VS5Q', 'Containers': 0, 'ContainersRunning': 0, 'ContainersPaused': 0, 'ContainersStopped': 0, 'Images': 4, 'Driver': 'overlay2', 'DriverStatus': [['Backing Filesystem', 'xfs'], ['Supports d_type', 'true'], ['Native Overlay Diff', 'true']], 'SystemStatus': None, 'Plugins': {'Volume': ['local'], 'Network': ['bridge', 'host', 'macvlan', 'null', 'overlay'], 'Authorization': None, 'Log': ['awslogs', 'fluentd', 'gcplogs', 'gelf', 'journald', 'json-file', 'local', 'logentries', 'splunk', 'syslog']}, 'MemoryLimit': True, 'SwapLimit': True, 'KernelMemory': True, 'CpuCfsPeriod': True, 'CpuCfsQuota': True, 'CPUShares': True, 'CPUSet': True, 'IPv4Forwarding': True, 'BridgeNfIptables': True, 'BridgeNfIp6tables': True, 'Debug': False, 'NFd': 22, 'OomKillDisable': True, 'NGoroutines': 38, 'SystemTime': '2019-04-18T23:06:19.983023943+09:00', 'LoggingDriver': 'json-file', 'CgroupDriver': 'cgroupfs', 'NEventsListener': 0, 'KernelVersion': '3.10.0-957.10.1.el7.x86_64', 'OperatingSystem': 'CentOS Linux 7 (Core)', 'OSType': 'linux', 'Architecture': 'x86_64', 'IndexServerAddress': 'https://index.docker.io/v1/', 'RegistryConfig': {'AllowNondistributableArtifactsCIDRs': [], 'AllowNondistributableArtifactsHostnames': [], 'InsecureRegistryCIDRs': ['127.0.0.0/8'], 'IndexConfigs': {'docker.io': {'Name': 'docker.io', 'Mirrors': [], 'Secure': True, 'Official': True}}, 'Mirrors': []}, 'NCPU': 2, 'MemTotal': 1907965952, 'GenericResources': None, 'DockerRootDir': '/var/lib/docker', 'HttpProxy': '', 'HttpsProxy': '', 'NoProxy': '', 'Name': 'localhost.localdomain', 'Labels': [], 'ExperimentalBuild': False, 'ServerVersion': '18.09.5', 'ClusterStore': '', 'ClusterAdvertise': '', 'Runtimes': {'runc': {'path': 'runc'}}, 'DefaultRuntime': 'runc', 'Swarm': {'NodeID': '', 'NodeAddr': '', 'LocalNodeState': 'inactive', 'ControlAvailable': False, 'Error': '', 'RemoteManagers': None}, 'LiveRestoreEnabled': False, 'Isolation': '', 'InitBinary': 'docker-init', 'ContainerdCommit': {'ID': 'bb71b10fd8f58240ca47fbb579b9d1028eea7c84', 'Expected': 'bb71b10fd8f58240ca47fbb579b9d1028eea7c84'}, 'RuncCommit': {'ID': '2b18fe1d885ee5083ef9f0838fee39b62d653e30', 'Expected': '2b18fe1d885ee5083ef9f0838fee39b62d653e30'}, 'InitCommit': {'ID': 'fec3683', 'Expected': 'fec3683'}, 'SecurityOptions': ['name=seccomp,profile=default'], 'ProductLicense': 'Community Engine', 'Warnings': ["WARNING: API is accessible on http://0.0.0.0:5555 without encryption.\n Access to the remote API is equivalent to root access on the host. Refer\n to the 'Docker daemon attack surface' section in the documentation for\n more information: https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface"]}
4.0.0-dev
コンテナ作成
stack = c.create_container(image='uphy/ubuntu-desktop-jp:18.04',detach=True,host_config=c.create_host_config(port_bindings={8080: ('0.0.0.0', 8080)},storage_opt={"size":"1g"}),stdin_open=True)
print(stack["Id"])
print(stack["Warnings"])
print(c.start(stack))
ポートは{コンテナ内ポート:(IP,ホストのポート)}で一対一対応とします。
また、storage-optはホストが対応していれば利用可能です。原則としてすべてのargsがdocker-pyに実装されています。
イメージのpull
for line in c.pull("uphy/ubuntu-desktop-jp:18.04", stream=True):
print(line)
forで回して待機しておかないと、あとあとの処理のときにimage取得完了前にコンテナを作成しかねません。
コンテナのexport
con = c.export("eee126213653")
f = open('./busybox-latest.tar', 'wb')
for chunk in con:
f.write(chunk)
f.close()
コンテナIDを指定することで「export」できます。exportはdocker exportと似た振る舞いをします。
コンテナのimport
何故か読み込み方法が複数あります。
repository,tagは指定しないと以下のようになります。
#<none> <none> c49ad9dfe280 12 minutes ago 1.42MB
tarとして読み込む
c.import_image_from_file(filename="./busybox-latestgetimage.tar",repository="title-busy",tag="latest")
dataとして読み込み。
c.import_image_from_data(data=open("./busybox-latestgetimage.tar","rb").read())
urlで指定して、tarfileを取得。
c.import_image_from_url(url="foo.com")
イメージのsave
image = c.get_image("busybox:latest")
f = open('./busybox-latestgetimage.tar', 'wb')
for chunk in image:
f.write(chunk)
f.close()
image save tarballでイメージを取得. docker save
に似ています。 https://github.com/docker/docker-py/blob/02e660da12ecb5cf755b17ffd850ce3da21ecec0/docker/models/images.py#L87
イメージのload
docker.api.image.ImageApiMixin.get_image (docker save
)で取得したデータをdocker load
のように読み込めます
tar = tarfile.open("./busybox-latestgetimage.tar", "r|")
print(c.load_image(data=tar))
#busybox latest af2f74c517aa 11 days ago 1.2MB
c.load_image(data=open("./busybox-latestgetimage.tar","rb").read())
コンテナ内の指定ディレクトリでtarを作る
f = open('./sh_bin.tar', 'wb')
bits, stat = c.get_archive(stack, '/dirname')
print(stat)
for chunk in bits:
f.write(chunk)
f.close()
コンテナ内の指定ディレクトリにtarballを展開する
c.put_archive(stack,"/path",tardata)
tardataはbytesです。
コンテナの停止
c.stop(stack)
サンプル
参考
https://nisenabe.hatenablog.com/entry/2014/01/21/104701
https://docker-py.readthedocs.io/en/1.2.3/port-bindings/
Author And Source
この問題について(docker-pyで docker daemonを遠隔操作してみようのコーナー), 我々は、より多くの情報をここで見つけました https://qiita.com/haniokasai/items/046e4a637cefe5500dd9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .