#Noob ahoy!
1 messages ยท Page 1 of 1 (latest)
Either way, I get a no file or directory error. I can cat for the file with the same directory and cat shows the file. So, I'm a bit perplexed.
How about getting the file in Go so Container().Build(dockerFile) will work? Maybe I'm just doing that wrong? This is my function currently.
func (m *MyModule) BuildContainer(
ctx context.Context,
imageName string,
dockerFile string) *Container {
dockerFile := dag.Directory().Directory(dockerFile)
builtContainer := dag.
Container().
Build(dockerFileDir)
return builtContainer
}
I'm very new to Go and Dagger, so go easy on me. ๐
Either way, I get a no file or directory error. I can cat for the file with the same path and cat shows the file. So, I'm a bit perplexed.
How about getting the file in Go so Container().Build(dockerFile) will work? Maybe I'm just doing that wrong? (Maybe I'm doing everything wrong. Haha! ๐ ) This is my function currently.
func (m *MyModule) BuildContainer(
ctx context.Context,
imageName string,
dockerFilePath string) *Container {
dockerFile := dag.Directory().Directory(dockerFilePath)
builtContainer := dag.
Container().
Build(dockerFile)
return builtContainer
}
I'm very new to Go and Dagger, so go easy on me (haha... pun not intended). ๐
dockerFile := dag.Directory().Directory(dockerFilePath)
I think you are using Directory() twice.
could you try this instead : dockerFile := dag.CurrentModule().Workdir(dockerFilePath) ?
I'm very new to Go and Dagger, so go easy on me (haha... pun not intended). ๐
No worry :)! I'm more a typescript developer more I really start to like
dag.Directory() gives you a new and empty directory in Dagger. So when you dag.Directory().Directory(dockerFilePath), you're looking for that file in that empty directory ๐ You want to get the Dockerfile either as a *File argument or with a *Directory argument, in case you need to load a docker build "context" for it.
@warm latch - Yeah, when I read the API docs on Directory, I was saying to myself, is this right? I guess I should have followed my instincts and dropped that direction.
Can you help with "You want to get the Dockerfile either as..."? Is this then just using regular file methods from Go?
Also, when you say a "docker build context", I do believe I'm missing the understanding about what a context is in Dagger.
For build context, depends on what you're doing in your Dockerfile. Do you have COPY instructions for example? See https://docs.docker.com/build/building/context/
Yes I do in fact. Ah, so it's the context of the build from the point of view of the docker image/container build?
Yes, it's essentially a directory. You pass a directory to Container.Build and Dagger, by default, looks for the dockerfile with path Dockerfile in that directory, but you can provide an alternative path if you have another name. So to get this directory in your function, you just set it as an attribute to the function:
func (m *MyModule) BuildContainer(source *Directory) *Container {
builtContainer := dag.
Container().
Build(source)
return builtContainer
}
Then you provide it via CLI:
dagger call build-container --source=../some/dir
So, Dagger knows, because it is a `Directory type, to automatically use it accordingly? What kind of Voodoo is that? LOL! ๐
Yes, and the function doesn't care where it came from. It could be a local host past, a remote git reference, from http, etc...
Let me see how far I get with this knowledge. I need to learn also how Dagger (or rather Go) can infer the type and work off of it accordingly. The course I took on Go definitely did not cover this. ๐
Well, there's some "magic" that dagger does for you but I can explain. I don't know whether it'll help understand or get you more confused with extra information since you say you're new to Go ๐
Essentially, when you call dagger through the CLI, it loads your module and the Go SDK parses your code to find your functions. It knows about the signatures of those functions and so it knows that you have an argument that is a dagger.Directory. That's not Go native, it's a custom Dagger type: https://pkg.go.dev/dagger.io/dagger#Directory. If you look at your module's files, you'll see an internal/dagger.gen.go. That type is declared there and is automatically generated by the Go SDK.
The CLI, in turn, knows that your function needs a Directory too so it provides a flag that takes a string and tries to create an instance of Directory before passing it to your function. If you're interested, you can see the Go code that handles this: https://github.com/dagger/dagger/blob/2a340d9d0c2843dc84ae829b2e375871d4149c0e/cmd/dagger/flags.go#L203-L231
As you can see, it tries parsing the string that you pass via the CLI as a git URL, and then try a local path if that doesn't work.
I think I have found success?
Container evaluated.
That's not Go native, it's a custom Dagger type: https://pkg.go.dev/dagger.io/dagger#Directory. If you look at your module's files, you'll see an internal/dagger.gen.go. That type is declared there and is automatically generated by the Go SDK.
Yes. I understood that *Directory is a Dagger type. I just didn't know Dagger could infer from that to do other stuff, just because of the type. That is some black-boxy kind of activity I'd say. Though, let me ask this, would someone with a good Go background catch on to this and what should be happening? Or is it purely Daggeresque?
I think I also am getting the word "type" and how it is used in Go mixed up with my knowledge of TypeScript. Some paradigm changes are needed obviously. ๐
Maybe I should start with the TypeScript SDK and see how that works, since I have more experience. Hmm... ๐ค
Yes, it's all regular Go ๐ What's a bit different is the automatic code generation that's being dropped into your Go module. But that also is not that far out. Go itself has primitives for code generation and several tools use this kind of stuff.
When I mean "type", in Go it's basically a struct.
In TypeScript it's a class. All SDKs do this code generation into whatever's native to the language.
And it all works through a GraphQL API. That's how a Go Dagger Module can call functions from a Python Module, and how the Dagger server puts it all together, as well as the CLI. It's all normalized through GraphQL so you may notice some terminology that comes from this, like "types".
Missed this. Yes, that means you haven't specified what you want to do with the returned Container, so it just built successfully. You can try adding terminal in the CLI to get in an interactive container and look around. Or you could do publish --address=ttl.sh/my-image to publish it to a registry, etc...
There's more docs coming for working with files and directories in this PR: https://github.com/dagger/dagger/pull/6918
Is there a way to see the output while the container is building?
Yes, you can increase verbosity from -v to -vvv, add --debug for even more, or connect to Dagger Cloud.
dagger call build-container --source=../some/dir --debug
--debug may be too much, I suggest you start with -v and increase if you need more.
dagger call doesn't have a -v flag, does it?
It does. It's a global flag, every dagger command supports it.
Hmm.. I've tried it in different places and some come up with no such flag errors or the dagger help pops up.
That's new in v0.11.0, released yesterday.
As I said, the -v flag is new in v0.11.0, which was released yesterday.
Ah.... hehe...
For v0.10.2, try --debug.
Got it!!!
On to the next problem(s). ๐
When I run the same function again, the "Container evaluated." returns much faster. I would guess this is the cache kicking in, which is cool. But, how do I reference the container to use it in the next dagger call? Also, is one task per function a best practice?
It's up to you, and how you'll use it, but I'd say yes, it's best to keep functions more atomic. However, it's also better to have some functions compose others, rather than trying to "stitch" via the CLI.
So let's say you have a Build function, a Test function and a Publish function. Both Test and Publish would run Build, but possibly Publish could run Test as well, before publishing.
In either case, wathever you want, you're just calling what you need. Could be just the build to test it: dagger call build terminal.
Or full on dagger call publish.
But best to compose in functions rather than results of different CLI commands.
For now, I'm just trying to learn. So, keeping functions simple. I've gotten my container built. Yay. Now I'd like to get it uploaded to docker hub, so I need credentials too. I was thinking args for them, so they aren't hard coded. I'll move to env vars via secrets or config maps later.
