Proof Of Concept: incus-compose

Warning: There be dragons here!!

I have been working on a proof of concept with the spirit of “docker-compose” but the soul of Incus. It is extremely rough, but the “up” and “rm” commands work. I’m posting it here, soliciting feedback on whether it’s a valuable idea in general, and how people might want to work with such a tool.

Here is the repo - seriously, it’s PoC code, so play on test systems.

I’m using this as-is already to manage my homelab Incus server. If it interests you, take a look at the README, the code, or even build it yourself and let me know if you think the idea has merit.

The code is what I would consider “early garbage”, there’s a mix of the Incus cli and api, which will certainly break usage against non-local servers. Not much error handling at all. Happy-path is incus-compose up and incus-compose down. incus-compose generate will create a sample compose file for you, but the one in the README is more complete.

Let me know what you think.

Brian

6 Likes

Having an Incus compose is very close to my ideal setup tbh, I will be following this closely.

Incus is way easier than anything that followed up on Docker as soon as you have stateful workloads involved, and being able to just run OCI images for the trivial case of a stateless workload in 6.3 is great. This also makes composing straightforward.

1 Like

Significant progress has been made here. Notably:

  • Now using the actual compose-spec library instead of a made-up spec. This means for many cases incus-compose up will work with a regular docker-compose yaml file.
  • nearly all of the cli calls to incus have been removed and replaced with api calls
  • added compose extensions like x-incus-gpu to extend the docker-compose spec where additional features of incus can be used - storage locations, snapshots, etc

Next up is defining some defaults that don’t violate the Principle of Least Surprise.

3 Likes

Are you kidding me? This feature is amazing. The best thing after, well, making Incus capable of running OCI containers?

  • Create Incus/OCI containers with code (which made docker what it is now).
  • Bring to Incus the most extended, de facto standard for app packaging and distribution, especially in the FOSS world.

Wouldn’t support of Dockerfiles be required too for this to be fully compliant with compose definitions? Or are Dockerfiles just for building images and compose for mixing images together?

2 Likes

docker-compose supports building images from dockerfiles with a “build” directive. I have no intention to support that. That use case is most frequently used for developers who are building multi-container services.

This morning I started an unmodified compose file for Gitea+postgres. Exciting!

1 Like

Screen recording here
Unmodified docker-compose file for gitea + postgres.

1 Like

For the brave, I created a release here

Big features missing:

  • run and exec. If you’re here you can probably figure out how to do that with the incus cli.
  • ports, expose. Still don’t know how to handle these. What would you expect to happen?

See the samples folder for the tests we’ve been using, and some examples of using attributes to control incus resources (snapshots, pool names, networks)

1 Like

Think the equivalent for Incus would be to use Incus proxy feature:

incus config device add container1 port80 proxy connect="tcp:127.0.0.1:3000" listen="tcp:0.0.0.0:80"

However, this isn’t really required if you deploy a stack. If all instances are using the same Incus network they can communicate directly with each other using the their local instance ports. Only the instances which requires access from the outside would need a Incus proxy.

Might be rather complex to find the right strategy?

Or integrate with an external proxy for “ingress”, like HAProxy

I made a change that makes incus-compose more like the docker version today. It creates a new managed bridged network named after the stack and puts the instances in that network. This sets the foundation for proxying, and also prevents instance naming collisions when stacks have services with the same name.

For the “expose” directive, I was considering adding an empty ACL to the network which would effectively prevent traffic from outside the instance’s network, then adding ACL rules for each exposed port. Still need to think that through more.