softprops / shiplift

🐳 🦀 rust interface for maneuvering docker containers
MIT License
624 stars 118 forks source link

Would you be interested in support for hyper 0.13 and rustls (replacing OpenSSL)? #226

Open emk opened 4 years ago

emk commented 4 years ago

Hello! I'm the maintainer of boondock, a barely-maintained Docker client for Rust. I'm hoping to migrate away from it at some point, and shipyard is on my shortlist.

There's one piece of potentially interesting code in boondock: A hyperlocal + rustls connection routine, which you can find here. The completely removes the dependency on OpenSSL, and it makes it easy to use the same code to talk to either unix:// sockets or https:// endpoints. It implements Docker-compatible certificate and key management.

If you'd be interested in supporting rustls at some point, I'd be happy to answer questions and maybe help with the integration. Thank you for maintaining a Docker client for Rust!

softprops commented 4 years ago

Thanks for reaching out @emk. I'll take a look. I've been waiting for a lot of the async ecosystem to shake out but I think most of the dust has settled. Any help would be welcome. There've been a handful of external start/stop attempts and moving this forward so the smaller the change the easier it would to drive it to completion

emk commented 4 years ago

Thank you for your response! I'm eagerly looking forward to the day that I can port cage to use shiplift, and then deprecate boondock in favor of your library. :-)

I agree that the async dust has mostly settled. I maintain several async Rust projects including dbcrossbar, bigml-parallel and geocode-csv. All of these now use async syntax and hyper 0.2 with no major problems. There are a few tricks but it's not bad once you get the hang of it.

The basic steps that I took to port boondock were:

  1. Build a new Connector type that handles HTTP, HTTPS and Unix sockets, and that knows how to use Docker TLS keys. This is pretty much a standalone component that can be reused anywhere. My employer can make it available under the same MIT license as shiplift.
  2. Convert the hyper initialization code to use hyper 0.13, and make sure hyperlocal URIs are built using hyperlocal::Uri (because hyper won't accept them otherwise).
  3. Convert the lowest-level GET and POST routines to be async.
  4. Go through adding async and await as needed to make the compiler errors stop.

Step (4) was surprisingly fast. It took me about an hour for all the simple cases.

Once there's an async API, you might want to add an optional blocking API that's similar to reqwest::blocking. Here's how I call async APIs from regular code:

        // Start a local `tokio` runtime for async calls.
        let mut rt = runtime::Builder::new()
            .basic_scheduler()
            .enable_all()
            .build()?;

        // Modify async calls to to use `rt.block_on`.
        let containers = rt.block_on(docker.containers(opts))?;

So it's pretty easy to provide a blocking wrapper around a basically async library.

Take a look at connector.rs and let me know what you think. The rest of the boondock is fairly messy, because I've never had enough time to modernize the code I inherited.

glynnk commented 3 years ago

The rustls implementation is dependent on webpki, which does validation on the hostname of the DOCKER_HOST.

What this means is, if your trying to connect to any DOCKER_HOST that's specified with an IP, rather than a hostname, hyper-rustls will prevent the call to the docker engine API.