Search code examples
c#docker.net-corecontainersconsole-application

Intercept Keyboard Key presses into a docker container


I'm trying to wrap a console application game into a docker container and it's necessary to catch the arrow key pressed on keyboard.

The code is:

public static Direction ReadInputDirection()
{
    var key = Console.ReadKey(intercept: true);

    switch (key.Key)
    {
        case ConsoleKey.UpArrow:
            return Direction.Up;

        case ConsoleKey.DownArrow:
            return Direction.Down;

        case ConsoleKey.LeftArrow:
            return Direction.Left;

        case ConsoleKey.RightArrow:
            return Direction.Right;

        default:
            return Direction.Invalid;
    }
}

The code above throws the following exception:

Unhandled Exception: System.InvalidOperationException: Cannot read keys when either application does not have a console or when console input has been redirected. Try Console.Read. at System.ConsolePal.ReadKey(Boolean intercept) at SnakeGame.Control.ReadInputDirection()

I'm using the following command to run the container where snake-game is the image name.

docker run -i --name snake-game snake-game

Is there any way to work around this problem ?


Solution

  • You need to pass the -t flag in addition to -i to docker run:

    -t              : Allocate a pseudo-tty
    

    That's another way to say "attach a terminal to the program". The docs are fairly explicit about it:

    For interactive processes (like a shell), you must use -i -t together in order to allocate a tty for the container process. -i -t is often written -it as you’ll see in later examples.

    Without a terminal (aka tty), the program has no way to read input and errors out, like you are seeing.