Native Shell Access to Containers

I’m having trouble trying to get a console that isn’t in the web UI. Part of my usual process when working with Rails applications is to attach to a running container and run various administration commands via the rails console.

I can’t find anywhere in the API that would allow me to attach to STDIN and STDOUT for a container so my only option currently is using the web UI which is inconvenient and not the best experience outputting log data. This also prevents me from doing automated tasks from CI environments such as running migrations.

After reading through the forums I saw someone suggest downloading the machine config, getting the ssh-key, ssh-ing into the host then running docker exec $CONTAINER_ID bash directly but this is a very involved and manual process. Even exposing the machine config from the API would be helpful here as I could query the container/stack name, find it’s host, then download the config and script the whole process to get a tunnelled ssh connection.

Are there any plans to offer such functionality in the future?

I was able to find some information on the API but I’m not 100% clear on which commands to send to the websocket endpoint once the terminal is created.

  • POST /v1/containers/:id?action=execute
  • Connect to the wws:// url in the API response
  • Can’t find documentation from here for websocket communication

The command you supply in the body of the POST is run with the equivalent of docker exec and the resulting WebSocket is binary and sends/receives frames that directly connect stdin/out from the command.

tty defaults to true so you probably want to change it to false unless you speak VT100 :smile:. The UI contains a terminal emulator and the Shell action is is roughly calling it with

{
  "command": ["/bin/bash"],
  "attachStdin": true,
  "attachStdout": true,
  "tty": true
}

(the actual command is much longer and weirder to handle cases where bash isn’t available and some other edge cases)

Thanks @vincent those comments were very helpful.

I created https://github.com/marcqualie/rancher-shell which allows me to carry on my workflow as I’m used to. Very basic currently but does everything I need and is more convinient than the web UI when working with a few environments simultaneously.

Looking through the source code of rancher-ui was also extremely helpful when building the frames and knowing to base64 encode/decode the data.

Really enjoying Rancher and looking forward integrating it deeper into our infrastructure.

ah d’oh, I forgot about the base64 because it’s not actually a binary socket :smile:. Cool project, thanks for sharing.

@vincent is there a timeout on the WebSocket or the container? If I leave the session idle for about 15 seconds it disconnects every time.

I can’t find any documentation on a timeout period or a ping command to keep the connection alive.

There is no timeout on our side… Are you doing SSL termination or similar proxying?

Ah, that may explain it. I have https://github.com/tutumcloud/haproxy in front of the rancher server for SSL termination and proxy-ing. Looking at their docs it seems their default timeout is 50s so I may see if I can increase it for just wss:// connections and see if that fixes it.

I did something which worked well. I run my command in a screen as part of the command.

In a “Run Once” container you use screen rails c or equivalent. Just start it with screen. Then after it has started you can use “Execute Shell” and in the shell you do screen -x to join the screen previously started.

A few extra commands and you have to have screen installed on the container. But the advantage is the console stays running.

EDIT:

Nevermind. The screen does not stay active after you do a single “Execute Shell”. So it only stays alive for one session. It is not persistent. Not too bad, but annoying that you cannot have a persistent console. I tried a few combinations of Interactive and TTY.

HI marcqualie

I see Rancher or Shipyard can make Terminal on web browser to container.
I know they use API docker, but I do not know how to do.
you can talk in more detail is not?
Thank you.

Hey @toanpt3

I am not sure exactly how it’s done within rancher internals, but they expose the functionality over websockets to make the integration simple for the web browser integration. The tool I created above (https://github.com/marcqualie/rancher-shell) uses that exposed websocket technology to allow the same functionality from the command line.

@vincent shared the documentation above for the websockets (http://docs.rancher.com/rancher/api/api-resources/containerExec/) and may be able to shed some light on the internals if you are wanting to build this kind of functionality directly on top of the Docker API.

The way it works in Docker is calling exec in the Docker Remote API on the host and running a shell like bash: https://docs.docker.com/engine/reference/api/docker_remote_api_v1.20/#exec-create . There’s also an equivalent in the CLI: https://docs.docker.com/engine/reference/commandline/exec/

hi
Thank you for the feedback, the problem I want to be able to use the API directly Docker https://docs.docker.com/engine/reference/api/docker_remote_api_v1.23/
Currently you have solved this problem yet?. If the matter has not been, we can exchange its own in this regard.

Thank you very much.

@marqualie
I felt also a bit limited by the built-in shell provided by rancher. So I have tried this shell web application "gotty"

Here is the docker version

https://hub.docker.com/r/dit4c/gotty/

It works quite well. Maybe worth giving it a try.

Hi @marcqualie.

I have enable debug on rancher, i get websocket URL:

After,i use wscat to connect this URL socket, connected but cannot execute command sample Rancher shell exec on web:

What did I do wrong?, I want one interface or as the exec shell rancher to do?
Thank you

The websocket frames are base64 encoded in both directions (because they can contain control chars and invalid what looks like UTF-8 sequences, etc… But binary frames are a pain).

Also the token is generated from the previous request to the exec action, and that is where the command to execute goes. And the tokens are only good for 5 minutes once issued.

Hi finally we have solution now.

We just created a very powerful rancher ssh cli to get this done:
https://github.com/fangli/rancherssh

Native SSH Client for Rancher Containers, provided a powerful native terminal to manage your docker containers.

You may want to give it a try, stars are welcome!

1 Like