Java Docker API Client relying on plain Socket
Switch branches/tags
Nothing to show
Clone or download
Pull request Compare This branch is 33 commits ahead, 1 commit behind ndeloof:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.circleci
src
.gitignore
README.md
jocker.png
pom.xml

README.md

Jocker, a Java client library for Docker API

Jocker is (yet another) Docker Client library to access Docker API.

logo

Primary goals are to "keep it simple stupid" and avoid dependency on third-party libraries

Limited dependencies

Most docker client libraries rely on other libs, typically Rest frameworks like Jersey or a full featured HTTP client like Apache Http Client or Netty.

Jocker has been created in the context of Jenkins Docker plugin development. Third party dependencies are constrained in Jenkins by core dependencies, introducing various classpath issues.

Also, such helper libraries demonstrated to have issues supporting some uncommon HTTP usage in docker APi, like Hijacked HTTP connection to attach stdin/stdout in interactive mode, or the /var/run/docker.sock Unix Domain Socket.

For JSON (un)marshalling we rely on Google Gson as a tiny (standalone), simple and efficient JSON library.

KISS (Keep It Simple Stupid)

API model is generated from the Docker official swagger specification. Some pull-requests have been made to help improve this API spec and ensure we get a clean model generated. For the few corner cases where the generated model doesn't offer a nice API, we maintain some dedicated model classes.

We directly implement HTTP over a java.net.Socket. This allows transparent support for Unix Domain Socket thanks to junixsocket.

We don't claim to offer a full featured HTTP client, just implemented what's required for a Docker API server. HTTP, a plain value protocol, is easy to debug and to implement, with only some limited features required by Docker API. The HTTP client implementation is about ~100 lines of code. Doing so we have full control on how HTTP protocol is used, and typically can implement HTTP connection Hijack without any hack.

License

Licensed under BSD Copyright 2017 Nicolas De Loof, CloudBees.

tl;dr: You're free to use this code, make any changes you need, have fun with it. Contributions are welcome if you do something you consider useful :P

Future plans

  • implement all APIs
  • a fluent client for those who prefer this programming model
  • use java.nio Channels and jnr-unixsocket to rely on non-blocking I/O
  • conquer the world

Supported APIs :

Missing something ?

If you miss some API support in following list, please consider contributing. In most cases, this is just a question of implementing few lines of code. API type is already generated from docker's swagger API contract, so you only have to implement the method invocation based on API documentation.

public SomeType apiMethod(String param) {
    StringBuilder path = new StringBuilder("/v").append(version).append("/some/api?param=").append(param);
    Response r = doGET(path.toString());
    return gson.fromJson(r.getBody(), SomeType.class);
}

General purpose

Containers

Images

Exec

Networks

TODO

Volumes

TODO

Swarm

TODO

Nodes

TODO

Services

TODO

Tasks

TODO

Secrets

TODO

Plugins

TODO

Config

TODO

Debug / Reverse engineering

There's few places where the docker API is not well documented, for sample ImageBuild operation documentation doesn't tell us much about the outputstream. In such circumstances we will have to reverse-engineer the docker API. Two (complementary) options here :

  1. read source code. If you're not familiar with Go this might be a bit challenging, but one learns a lot about the API looking at this.
  2. analyze HTTP traffic produced by docker CLI. For this purpose I use dockins/dockersock docker image to expose my docker4mac socket in plain HTTP :

docker run -it -v /var/run/docker.sock:/var/run/docker.sock -p 2375:2375 dockins/dockersock

Then I use Wireshark with filter tcp.port=2375 to capture HTTP frames sent by client and daemon response.