Recently, I was writing a script whose function was to retrieve and parse a list of processes that were running in a docker container. The script was based on another script that did the same by ssh-ing to a remote server. However, my grep/sed/awk command set did not work despite the printed output in the terminal looked identical to the one from the original script.

docker logo

This is a simplified version of the command:

1
2
$docker exec -it container_name echo "Hello”
Hello

As you may see, the output looks very normal. I decided to print the output with C-styled escaped characters using the od utility:

1
2
3
$docker exec -it container_name echo "Hello" | od -c
0000000    H   e   l   l   o  \r  \n
0000007

You may notice that the output contains the carriage return character(\r)! In contrast, the ssh output does not:

1
2
3
$ssh user@remote_server "echo Hello" | od -c
0000000    H   e   l   l   o  \n
0000006

In order to understand where the difference comes from, we need to take a look at the parameters of docker exec -it. By default, docker containers have only STDOUT attached, therefore a container’s output is printed to the host’s terminal. If a user needs to send an input to the container, the container has to have STDIN open. In order to do so, you need to run docker exec -i or docker exec --interactive=true. It is likely that most applications don’t need more parameters except those that use the TTY features, such as text coloring or curses. To provide them with this ability, the container has to run with -t or --tty=true. A good example of such an application is vim. The only way to use vim inside a container is to run/execute the container with -it.

It seems that the default behavior of tty is to add the carriage return.

In my case, I did not actually need STDIN nor TTY, so I ran the container without -it:

1
2
3
$docker exec container_name echo "Hello" | od -c
0000000    H   e   l   l   o  \n
0000006

The result is no carriage return!

In case you do need TTY but don’t want the carriage return, there are a few options: Delete \r from the container’s output using tr:

1
2
3
$docker exec -it container_name echo "Hello" | tr -d '\r' | od -c
0000000    H   e   l   l   o  \n
0000006

Configure the container’s TTY to translate newline to carriage return-newline:

1
2
3
$docker exec -it container_name /bin/bash -c "stty -onlcr && echo 'Hello'" | od -c
0000000    H   e   l   l   o  \n
0000006

Note: all of the above applies to docker run as well.

Please share your thoughts on LinkedIn.