Skip to content
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

Allow dokku run to support interactive commands #236

Closed
rajivm opened this issue Oct 9, 2013 · 19 comments
Closed

Allow dokku run to support interactive commands #236

rajivm opened this issue Oct 9, 2013 · 19 comments

Comments

@rajivm
Copy link
Contributor

rajivm commented Oct 9, 2013

Currently the dokku command supports 'run' to allow executing a command within the docker container of an app; this is useful for things like Django's manage.py syncdb.... but it doesn't allow any interactivity, whereas Heroku allows interactive commands in its equivalent. This is useful for responding to prompts from a command, or launching a shell within the container.

@asm89 asm89 closed this as completed in 4f86047 Oct 9, 2013
asm89 added a commit that referenced this issue Oct 9, 2013
resolves #236, adding support for dokku run commands to be interactive
@mikexstudios
Copy link
Contributor

The Problem

I would like to reopen this ticket since the change broke the run command for locally executed commands. The current line 19 of plugins/00_dokku-standard/commands has:

docker run -i -t $IMAGE /exec "$@"

The -i -t options are to (from docker docs):

-i=false: Keep stdin open even if not attached
-t=false: Allocate a pseudo-tty

If, logged into the server through ssh, I run:

root@server:~# dokku run myapp ls
root@server:~# 

Nothing is printed. However, if I change line 19 to:

docker run $IMAGE /exec "$@"

or even:

docker run -i $IMAGE /exec "$@"

or even:

docker run -t $IMAGE /exec "$@"

and re-run a command, I get:

root@server:~# dokku run myapp ls
... bunch of files printed ...
root@server:~#

rajivm did not have this issue since he's calling dokku run through ssh (see: http://blog.rajivm.com/your-own-mini-heroku-for-5-dollars-per-month.html), like:

ssh root@server dokku run myapp ls

which then returns output but requires a final Ctrl-C to quit ssh.

The problem is that docker's -i -t option does not play well with sending output to stdout if the docker run -i -t command is inside of a shell script.

Proposed Solution

One way to resolve this, while retaining the ability to run interactive commands, is to remove the -t option from line 19:

docker run -i $IMAGE /exec "$@"

This enables both local and remote execution of commands. The drawback is that remote execution of bash is stunted since a pseudo-tty isn't allocated. So you cannot see the command line prompt. (But you can still use the shell.) But I think that's fine since the user can ssh into the dokku server normally anyway.

@asm89 asm89 reopened this Oct 13, 2013
@asm89
Copy link
Contributor

asm89 commented Oct 13, 2013

@mikexstudios Can you send a PR for removing the -t option?

Thinking if we can detect that we have to allocate a pseudo-tty so it can work for both versions. :)

@rajivm
Copy link
Contributor Author

rajivm commented Oct 13, 2013

I think the issue has to do with how pluginhook is running the plugin "run" command:

While with -i -t

dokku run myapp ls

fails when running directly on the server... running the shell script:

#!/bin/bash
docker run -i -t app/myapp /exec "ls"

does not... and, similarly, if I make "commands" executable,

./plugins/00_dokku-standard/commands run myapp ls

does not fail also.

So then I tried inlining the "run" plugin into the main "dokku" script, and again it worked fine (both locally and remotely over ssh).

Still investigating...

@mikexstudios
Copy link
Contributor

rajivm is right. I will hold off on sending a pull request until the root issue can be uncovered. I'll see if I can figure anything out too.

@rajivm
Copy link
Contributor Author

rajivm commented Oct 13, 2013

pluginhook also causes "ls" and similar commands not to auto-terminate when running remotely; however, without pluginhook, the command runs and then ssh disconnects.

@rajivm
Copy link
Contributor Author

rajivm commented Oct 13, 2013

if [ -t 0 ] ; then

is false when running from pluginhook, versus when running from a normal shell script... this means the output stream is no longer attached to a tty.

@asm89
Copy link
Contributor

asm89 commented Oct 13, 2013

Let's see if @progrium has any pointers. :) ping!

@mikexstudios
Copy link
Contributor

Quick update:

It seems that in https://github.com/progrium/pluginhook/blob/master/pluginhook.go, cmds[i].Stdin = os.Stdin and cmds[i].Stdout = os.Stdout are not being set when -t -i are being used. Setting Stdin and Stdout manually results in output for dokku run myapp ls. I suspect that the if statements isn't catching all of the cases...

@asm89
Copy link
Contributor

asm89 commented Oct 13, 2013

What happens if you try the following with the 'original' pluginhook?

echo test | dokku run myapp ls

@rajivm
Copy link
Contributor Author

rajivm commented Oct 13, 2013

@asm89 that also returns nothing (using the original pluginhook).

@rajivm
Copy link
Contributor Author

rajivm commented Oct 13, 2013

@@ -38,7 +37,7 @@ func main() {
                        }
                        cmds[i].Stdin = stdout
                }
-               if i == 0 && !terminal.IsTerminal(syscall.Stdin) {
+               if i == 0 {
                        cmds[i].Stdin = os.Stdin
                }
                go func(cmd exec.Cmd) {

allows dokku run myapp ls to work locally, but it hangs at the end (just as remote was), and -t 0 still is false

@rajivm
Copy link
Contributor Author

rajivm commented Oct 15, 2013

Until we can resolve the issue with pluginhook-- one temporary solution that we could merge in (and not close the ticket with) is to just inline the "run" plugin into the main dokku script. After we figure this out, we could move it back to the plugin. This would create the "least broken" experience for users in the meantime.

@progrium
Copy link
Contributor

Super interested in fixing pluginhook once we know what we want.

On Mon, Oct 14, 2013 at 9:09 PM, Rajiv Makhijani
notifications@github.comwrote:

Until we can resolve the issue with pluginhook-- one temporary solution
that we could merge in (and not close the ticket with) is to just inline
the "run" plugin into the main dokku script. After we figure this out, we
could move it back to the plugin. This would create the "least broken"
experience for users in the meantime.


Reply to this email directly or view it on GitHubhttps://github.com//issues/236#issuecomment-26308102
.

Jeff Lindsay
http://progrium.com

@mikexstudios
Copy link
Contributor

Hey Jeff,

pluginhook seems to have a major issue that is preventing interactive execution of commands through dokku:

  • When pluginhook executes docker run -i -t app/myapp /exec ls, no output is received. If a bash script is used to execute the same, expected output is generated. Both -i -t flags are required for interactive execution of commands.

A second minor issue is:

  • When pluginhook executes docker run -i app/myapp /exec ls (removed the -t flag to receive some output just to illustrate this issue), the correct output is received but the command does not terminate until a Ctrl-C is issued. If a bash script is used to execute the same, expected output is generated and script exits back to command prompt.

Can you investigate why pluginhook is behaving this way? Essentially, we want pluginhook to execute commands with the same behavior as bash scripts.

@plietar
Copy link
Contributor

plietar commented Oct 27, 2013

I tried to implement a "shell" command in dokku, which would give access to a shell running as the dokku user via ssh.
I have the same problem, running an interactive bash session from a pluginhook makes the session non interactive, where as it does work fine when running from the dokku file.

@asm89
Copy link
Contributor

asm89 commented Oct 30, 2013

@mikexstudios @plietar Do you think you can put together a small gist with a plugin and a script that shows the problem in an easy producible way?

@asm89
Copy link
Contributor

asm89 commented Oct 30, 2013

/cc @unclejack

@mikexstudios
Copy link
Contributor

I will try to get to this tomorrow or over the weekend. Thanks.

@unclejack
Copy link
Contributor

I've looked into this earlier this week. There are a few issues and the simplest solution will be to move the run command to the top level dokku shell script to avoid having to go through pluginhook.

I haven't discovered any bugs or problems in docker.

The main problems and questions are:

  • the hook execution code seems to be having a few problems; it's not detecting and handling execution failures properly
  • when a hook fails to execute, it's not handled properly; what should happen to the other processes? should they all be killed or should they all continue to run independently? If they should all run independently, why are hooks connected to each other? either way, exit codes need to be handled, timeouts have to exist and stalls require detection.
  • what exactly should pluginhook do? this is important when it comes to rewriting or fixing pluginhook
  • tty/ptys aren't set up when launching something via pluginhook; dokku was executing the run command like this: dokku shell script > pluginhook > shell script > command
  • stdin & stdout handling seems incorrect in pluginhook (unless this is how it was meant to be implemented)

I'm commenting so @progrium can keep track of these issues & concerns, as requested.

@ghost ghost closed this as completed Nov 22, 2013
mincedmit pushed a commit to ginlane/dokku that referenced this issue Feb 13, 2014
mincedmit pushed a commit to ginlane/dokku that referenced this issue Feb 13, 2014
resolves dokku#236, adding support for dokku run commands to be interactive
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants