#Containers running containers

1 messages ยท Page 1 of 1 (latest)

shell fog
#

Can you give me a quick summary of your use case?

#

To make sure I give you a useful answer

dawn flame
#

as part of a CI/CD pipeline, I'd like to have a container that runs terraform apply. During this step, I'd like a parallel container to be started that copies a file in a google cloud bucket.

#

So there would be two containers: one runs terraform and starts this second container, and waits for it to complete before continuing

shell fog
#

What language are you writing your Dagger Function in?

dawn flame
#

python, but I can read Golang

shell fog
#

OK

#

So, the general idea is that your Dagger Function is just regular code (in your case Python) and you can use that to implement any logic you want. That includes running things concurrently. You simply use your native language's concurrency features. In Go that's goroutines and error groups. In Python, I think task groups?

#

Then anywhere in your code, you can make calls to the Dagger API. The Dagger engine itself can handle any number of calls concurrently. You just need to make sure your client calls are sufficiently concurrent

#

Then it's a matter of exploring the Dagger API docs, and finding the right calls for what you want to do

dawn flame
#

I've seen it implemented with python's async capabilities in the documentation. my main issue is how to have these two containers run as two distinct containers on the host, so that I can clearly separate the dependencies required to run them, so the one thing I'm missing is how I start a separate container from within a dagger function that's by default already running in the module's container

shell fog
#

Lastly, you can also look in the Daggerverse for existing high-level functions, to save you time. For example, there are probably several terraform modules with ready-to-use functions for running "apply".

shell fog
#

In Dagger, everything is immutable, so if you make 2 calls to execute 2 containers, they will have nothing in common unless you explicitly pass the same input twice

#

Once you "grok" the basic concepts, Dagger code is very easy to reason about, because there are no side effects: all data flows in one direction through the dag

dawn flame
#

am writing you a quick example

#
@function
def run_terraform_code(self, terraform_dir: dagger.Directory) -> None:
    #logic to run the terraform code with the given directory

@function
#function called within the terraform code; it starts a new container and performs the transfer
def transfer_to_bucket(self, creds: dagger.Secret, bucket_name, destination_filename) -> None:
  #this is the part I wonder about, not the transferring logic but the making-a-new-parallel-container
#

@shell fog this is sort of how I was thinking of implementing it

shell fog
#

what is the relationship between those 2 functions?

dawn flame
#

the first runs through a dagger call run_terraform_code, the second gets called within that terraform code

shell fog
#

do you want to run terraform, then transfer the result?

#

gets called within that terraform code

Can you explain what you mean by this? You want run_terraform_code to call transfer_to_bucket ?

dawn flame
shell fog
#

oh wow, so it's a dagger function calling terraform calling another dagger function

dawn flame
#

yeah, it's split this way so the dependencies necessary to run the terraform code are separated completely from the dependencies needed to run the transfer_to_bucket container

#

i think this is the way to do it but i may absolutely be wrong

shell fog
#

Well, there are 2 separate topics here:

  1. Whether you need to go through terraform to call another dagger function. If you're doing this specifically to workaround limitations of dagger, then you probably don't need to. But if you're doing it for unrelated constraints in your project (like, you just want to do it with terraform) that's fine, and we can make it work.

  2. Assuming you do want to use terraform in this way, then how to get it to work

#

To address the first point: Dagger makes it very easy to run any number of containers each with their own dependencies, you have infinite control over this, and definitely don't need to wrap your function calls with terraform to achieve this.

#

As for point 2: regardless of point 1, if you do want to wrap a dagger call in terraform, it's perfectly possible. There is just one argument you need to pass to the withExec call running terraform, to enable "dagger in dagger" nesting.

#

(As a side note, I think it's time to enable that dagger-in-dagger nesting flag by default, wdyt @craggy lion @raw wolf ?)

dawn flame
#

wrt #1, it's to work around a limitation of terraform (there's a provisioning step that can't be taken care of in pure terraform and requires doing work outside of it, yet needs to account for it in order to completely represent the state of the infrastructure). I think we could potentially refactor this to work instead by making the call outside terraform, but then terraform wouldn't be able to work as a dashboard for the state of the infrastructure anymore

dawn flame
#

so I want to avoid if possible nesting containers

shell fog
#

You don't to worry about that, dagger-in-dagger nesting is not the same as nesting linux containers. From a system perspective they will not be nested.

dawn flame
#

ah fantastic!

shell fog
#

It's more like unix processes forking more unix processes. Completely normal, and the system is designed for it.

#

It's one of the most powerful features and under-appreciated features of Dagger actually ๐Ÿ™‚

dawn flame
#

I see. so does in fact calling container.from(image).withExec(command) produce a parallel container, not a nested one?

shell fog
#

The important thing is to set that flag I was talking about in withExec. Otherwise, the nested dagger call will not see an active session, and instead will try to bootstrap its own dagger engine - which will either fail, or actually result in a docker-in-docker situation (which you want to avoid)

dawn flame
#

ahhhh I see!

shell fog
dawn flame
#

okay I see right

shell fog
#

By the way, I recommend setting up a free Dagger Cloud account, and using the new Traces feature to visualize this

#

It just launched this week ๐Ÿ™‚

dawn flame
#

nice, will do!

#

i really think this stuff is about the revolutionize the game if it hasn't already

shell fog
#

That's the plan ๐Ÿ™‚ Thanks for your patience

dawn flame
#

thanks for taking the time!

raw wolf
# shell fog (As a side note, I think it's time to enable that dagger-in-dagger nesting flag ...

Yes, but would consider this PR to be a pre-req: https://github.com/dagger/dagger/pull/6916. Problem atm is dag-in-dag currently gets "too" isolated and is treated as a completely independent client, but that PR results in nested execs sharing the same server created by the original client while retaining isolation in the right parts (essentially, that PR makes nested execs the same as modules in terms of isolation). That PR keeps getting pushed in prio but hopefully will have time to finish it up soon.

Either way, I'll open an issue for enabling that by default once we can.

GitHub

GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.

dawn flame
#

to be sure: although enabling experimental_privileged_nesting gives the original dagger engine access to the commands ran with with_exec, if I want conainer.from(image).with_exec to run dagger call dagger_function, I still need to install dagger in that container, correct?

shell fog
#

would be cool if we added an API call to just mount that binary for you

#

There is a module for it though ๐Ÿ™‚

dawn flame
dawn flame
shell fog
dawn flame
#

nice!!

shell fog
#

Example of building the latest CLI release from source:

dagger call -m github.com/shykes/daggerverse/dagger@fcca1b35819c321058c0fb1392e58a17c5339c0f \
 engine \
 release --version=0.11.1 \
 source \
 cli --operating-system=linux --arch=x86_64 \
 export --path=./dagger-0.11.1
dawn flame
#

very neat!

shell fog
#

The equivalent in Go would be:

// Add the dagger CLI to a container
func addDaggerCLI(c *Container) *Container {
 daggerCLI := dag.
  Dagger().
  Engine().
  Release("0.11.1").
  Source().
  Cli()
 return c.WithMountedFile("/bin/dagger", daggerCLI)
}

Assuming you've installed the module with dagger install github.com/shykes/daggerverse/dagger

dawn flame
#

seems there are tons of little tidbits like this throughout the discord channel

#

I wonder if we could build a little llm scraper to collect them all into a little question/answers wiki

shell fog
#

Yeah, that's something we need to work on

#

First and most obviously, we're working on getting more of all this into the docs

#

We've also been testing various AI tools to help surface some of this info. Haven't found the perfect fit yet, but we're interested!