Sometimes, containers need to run programs like interactive shells, language REPLs (e.g., python
, node
, etc.),
or text editors (e.g., vim, nano, etc.).
Such programs require their STDIN to be a terminal to print colored output,
show cursor, and fit the content to the actual terminal window size.
However, containers are always background daemon-like processes.
Even though docker run
blocks your current shell when no -d
flag is provided,
it's the docker run
process itself that gets controlled by your shell's terminal.
The actual containerized process always runs in the background,
while its STDIO streams are just streamed back and forth to the foreground docker run
process.

How to run a background process under a control of a terminal?
By using a pseudo-terminal (TTY).
This is exactly what the docker run -t
flag does -
it allocates a pseudo-TTY (pty), and makes it a controlling terminal of the containerized application.
Let's see it in action. The challenge has a specially crafted container with the following Python program:
import shutil
import signal
import sys
import time
def print_size(msg):
cols, rows = shutil.get_terminal_size()
is_tty = sys.stdout.isatty()
print(f"{msg} size: {cols} x {rows} (cols x rows) is_tty={is_tty}")
def on_window_change(sig, frame):
# Print size on terminal window resize
print_size("Changed")
def main():
# Print the initial terminal window size
print_size("Initial")
signal.signal(signal.SIGWINCH, on_window_change)
print("Resize the terminal to see updates. Press Ctrl+C to quit.")
try:
while True:
signal.pause() # wait for any signal (incl. SIGWINCH)
except (KeyboardInterrupt, SystemExit):
print("\nExiting...")
if __name__ == "__main__":
main()
This simple script prints the current terminal size and also subscribes to the window change signal SIGWINCH
.
Launch the first container without using the -t
flag:
docker run registry.iximiuz.com/terminal-monitor
Now, resize the terminal pane (or the browser window) to see what happens when a pseudo-TTY is not allocated for the container.
Then, launch another container, but this time using the -t
flag:
docker run -t registry.iximiuz.com/terminal-monitor
One more time, resize the terminal pane (or the browser window) to see what happens when a pseudo-TTY is allocated for the container:
Finally, to put together the skills from this and the previous challenge,
launch an interactive Python REPL, using the python:3-slim
image:
Hint 1 💡
You need to combine the -t
and the -i
flags when using the docker run
command
because the Python REPL session is best when it's both TTY-controlled and can accept user input from the STDIN.
Level up your Server Side game — Join 11,000 engineers who receive insightful learning materials straight to their inbox