DockerはREST APIを提供しています。
$ docker build
や
$ docker run
といったコマンド操作は、内部的にはdocker deamonへの命令をREST API経由で行っており、
それはCLIだけでなくcurlやプログラムで直に叩くこともできます。
Docker Engineは、
- docker daemon
- REST API
- docker CLI
で構成されたクライアント&サーバ アプリケーションです。
https://docs.docker.com/get-started/overview/#docker-engine
Docker公式のSDK(Go, Python)が提供されていますが、Rustの勉強がてらRustで叩いてみました。
コード
use std::error::Error;
use std::path::Path;
use futures_util::stream::TryStreamExt;
use hyper::{Client};
use hyperlocal::{Uri, UnixClientExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
let path = Path::new("/var/run/docker.sock");
// API version はローカルにインストール済みのdockerのバージョンを確認する
let url = Uri::new(path, "/v1.40/containers/json");
let client = Client::unix();
let response_body = client.get(url.into()).await?.into_body();
let bytes = response_body
.try_fold(Vec::default(), |mut buf, bytes| async {
buf.extend(bytes);
Ok(buf)
})
.await?;
println!("{}", String::from_utf8(bytes)?);
Ok(())
}
hyperlocalのリポジトリのREADMEからほぼ引用のコードですが、そのままだと動作しなかったため、一部修正してます。
以下のコンテナの状況
でプログラム実行してみると、こんな感じで返ってきます。(文字列で出してるので表示が雑ですが。。)
hyperlocal
docker daemonはデフォルトでUNIX domain socket(/var/run/docker.sock)をリッスンするように設定されており、Hyper(RustのHTTPクライアント&サーバライブラリ)だけでなく、unixソケット通信を実現する hyperlocal を使用する必要がありました。
参考
[公式Doc]
https://docs.docker.com/get-started/overview/#docker-engine
https://docs.docker.com/get-started/overview/#docker-architecture
さわって理解するDocker入門