user12374570
user12374570

Reputation:

Write to stdin of running docker container

Say I run a docker container as a daemon:

docker run -d foo

is there a way to write to the stdin of that container? Something like:

docker exec -i foo echo 'hi'

last time I checked the -i and -d flags were mutually exclusive when used with the docker run command.

Upvotes: 12

Views: 14953

Answers (2)

Fritz
Fritz

Reputation: 1420

According to another answer on ServerFault, you can use socat to pipe input to a docker container like this:

echo 'hi' | socat EXEC:"docker attach container0",pty STDIN

Note that the echo command includes a newline at the end of the output, so the line above actually sends hi\n. Use echo -n if you don't want a newline.


Let's see how this looks like with the example script from David's answer:

# Create a new empty directory
mkdir x

# Run a container, in the background, that copies its stdin
# to a file in that directory
docker run -itd --rm -v $PWD/x:/x --name cattainer busybox sh -c 'cat >/x/y'

# Send some strings in
echo 'hi' | socat EXEC:"docker attach cattainer",pty STDIN
echo 'still there?' | socat EXEC:"docker attach cattainer",pty STDIN

# Stop container (cleans up itself because of --rm)
docker stop cattainer

# See what we got out
cat x/y

# should output:
# hi
# still there?

You could also wrap it in a shell function:

docker_send() {
    container="$1"; shift
    echo "$@" | socat EXEC:"docker attach $container",pty STDIN
}

docker_send cattainer "Hello cat!"
docker_send cattainer -n "No newline here:"    # flag -n is passed to echo

Trivia: I'm actually using this approach to control a Terraria server running in a docker container, because TerrariaServer.exe only accepts server commands (like save or exit) on stdin.

Upvotes: 13

David Maze
David Maze

Reputation: 158848

In principle you can docker attach to it. CTRL+C will stop the container (by sending SIGINT to the process); CTRL+P, CTRL+Q will detach from it and leave it running (if you started the container with docker run -it).

The one trick here is that docker attach expects to be running in a terminal of some sort; you can do something like run it under script to meet this requirement. Here's an example:

# Create a new empty directory
mkdir x

# Run a container, in the background, that copies its stdin
# to a file in that directory
docker run -itd -v $PWD/x:/x --name cat busybox sh -c 'cat >/x/y'

# Send a string in
echo foo | script -q /dev/null docker attach cat
# Note, EOF here stops the container, probably because /bin/cat
# exits normally

# Clean up
docker rm cat

# See what we got out
cat x/y

In practice, if the main way a program communicates is via text on its standard input and standard output, Docker isn't a great packaging mechanism for it. In higher-level environments like Docker Compose or Kubernetes, it becomes progressively harder to send content this way, and there's frequently an assumption that a container can run completely autonomously. Just invoking the program gets complicated quickly (as this question hints at). If you have something like, say, the create-react-app setup tool that asks a bunch of interactive questions then writes things to the host filesystem, it will be vastly easier to run it directly on the host and not in Docker.

Upvotes: 6

Related Questions