-
-
Notifications
You must be signed in to change notification settings - Fork 625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Docker Proof-of-Concept #974
Conversation
Will this support docker-compatibles? ( |
This looks awesome @andreynering ! From my perspective — albeit limited — if an early version would mount a volume of the local path, and allow passing some flags, that would be a great start already. If you want to allow |
@endigma I never had any contact with Podman yet. I mentioned it because some people have asked for it on the past. Is Podman CLIs compatible with Docker? The way I implemented it, Task is just generating a EDIT: The website says:
So yeah, seems that it would just work. Needs to be tested, though. |
Thanks for the credits. Looking forward to see support for docker in taskfile. May I can give you some advice/recommendations, since I had a lot of findings during the development of hammerkit. Use mounts for sources, volumes for generates.
Keep in mind about file permissions
Github Actions on windows with docker is difficult
I think the approach using the cli can work. The only downside will be getting information back from the cli. Status reporting on longer tasks, needs to read from the stdout or some background task needs to inspect the container. What you also should consider is, if you want to create multiple "docker run" commands for a task or create one container for each task and the use "docker exec" for the list of commands. The later one will be way faster and saves some resources/prep/post work. |
Thanks for the tips @no0dles! These are issues I didn't think I would face. Good reminder to test on different OSes as well. |
My current workflow consist of calling Task from inside Daggers Go-SDK. Maybe Task could leverage that to transparently execute tasks in Docker instead? It already gives you a way to interact with the docker daemon using Go, so why reinvent the wheel here? Or do I missunderstand the goals of this PR? |
I'm looking forward for this one to land. |
I decided to take a different approach, thoughts? |
We use Task extensively with containers. Generally the approach we have is:
Since it works already ... I wonder is it really necessary to support docker? Workflows around containers can be remarkably complex. When you try to formalise that within Task, then its possible to be "a sometimes useful, sometimes not" feature. If I would extend the schema, it might be like this:
but as it is, it looks like this:
Well, there might be something to it. For the minimal case, its a bit easier to work with. Perhaps, the problem is generalised even further ... a generic "runtime", which could be containers (docker, podman, kubernetes), but also things like ssh, terminal or other command interfaces. The minimal case, presented here, with a container runtime defined elsewhere ... does look like it would be easier to work with. |
This is an example taskfile that shows how we use docker. You can see, docker itself is not the bulk of the work ... Its also possible to define the docker command as a variable, and expand that in certain circumstances (typical use case is running task inside a container, then you don't need the docker command.
Also, related to #1568, in that file you can see how we solve the skip problem:
... but perhaps more interesting, is how we have to deal with optional arguments. Improving that might also be interesting. |
@trulede I lean towards this instead of integrating with specific tools. I think Task works better if the integration with tools is left to the user. Opening the door to integrations with tools is a slippery slope. It wouldn't be long before there is a feature request for an integration with everyone's favourite container tool or ssh client etc and this is a maintenance nightmare. I haven't actually used However, we should absolutely make it as easy as possible to integrate with other tools. There is an open issue (#448) that tracks the kind of functionality you're describing. I think this fulfils the spirit of the initial proposal here and I would personally vote to close this in favour of an implementation of that issue. For example: version: 3
tasks:
# Basic docker example
docker-stuff:
runtime: "docker exec my-container"
cmds:
- some-command-inside-my-container
- ...
# Slightly more interesting example using a variable in the `runtime` clause
kubernetes-stuff:
vars:
POD_NAME: service-1
runtime: "kubectl exec $(kubectl get pod -o name | grep {{.POD_NAME}})"
cmds:
- some-command-inside-my-pod
- ...
# Slightly more interesting example using a variable in the `runtime` clause
ssh-stuff:
vars:
USER: pete
SERVER: my-server
runtime: "ssh {{.USER}}@{{.SERVER}}"
cmds:
- some-command-on-my-server
- ... |
@pd93 What I have discovered is that the more complex operation is beyond the understanding of most of our users. To deal with that, I have wrapped most complex operations in a Taskfile. I think that works better than the suggested 'runtime' because it encapsulates all the complexity, rather than splitting it to several places (even in the same file, novice users generally can't visualise the abstractions behind task, and come up with "interesting" outcomes). That makes be wonder, is there another way to achieve both of these outcomes: 'task wrapping' and 'runtime', and perhaps also wrapping some other concepts to create a session like lifecycle for those commands to run/execute in. Could we think of it this way: the commands of this task, or even a subset of those commands, should run in that context, the context itself is also a task (i.e. specified by the task name). The context task, itself, runs all its commands to setup the context ... then runs the provided commands ... and then runs its own defer commands to cleanup/close the context. For a long running context (i.e. container/telnet etc.) the mechanism mentioned here (#1082) could be used to keep a context running between commands. When defining such a context task, it might then be necessary to indicate if such a context should be per invocation, or shared (similar to how 'run' determines how often a task runs), but generally it keeps the existing pattern of use.
Generally I agree. These runtimes, and the usage around them, are typically complex and specalised. A generalised approach would likely be more successful than attempting to support a specific tool. |
Closing in favor of #448. I started this PR as a proof-of-concept, but without being sure if it was a good idea or not. I end up not having enough time to return to this PR, as there was always smaller things that had higher priority. Considering that #448 would allow a wider range of use-cases, it looks much wiser to focus on that proposal instead of this one. Thanks everyone for the discussion! 🙂 |
NOTE: This is incomplete work. It's a proof-of-concept that is going well, but the actual behavior and schema will change until it reaches
master
, so avoid using this unless for testing purposes.Feedback is welcome on how you expect this to work 🙂.
Implementation
Credits given to @no0dles for the first PoC on #285 and its our tool hammerkit.
On his implementation, @no0dles used the official Docker client library for Go. Sounds reasonable, but I decided to try a different approach: I'm calling
docker run ...
directly. There's a couple of reasons this may be interesting:flags
prop on the YAML to allow the user to set specific Docker flags (flags: [--cpus=1, --pull=always]
). This would be harder to implement if using the Go client, would potentially require a prop to each setting. List of flags available here.TODO
flags
it's also possible to do this.dir
prop and its relation with themounts
prop.method/sources/generates
? Try to run them inside the container? Run outside? Forbid usage on when task is a container?container
prop, so it's possible to set all tasks on run in a given container?