When working with Docker containers running interactive applications (like Java programs listening to STDIN), developers often need to automate input delivery. The manual docker attach
approach doesn't scale for automated workflows.
The naive approach using docker exec
doesn't work because:
# This sends output to the exec session's STDOUT, not the main process STDIN
docker exec my-container echo "input-text"
Method 1: Using Named Pipes
Create a named pipe and attach it to the container:
# Host machine setup
mkfifo /tmp/container_input
docker run -it -v /tmp/container_input:/input my-java-image
# In another terminal
echo "your_input" > /tmp/container_input
Method 2: Direct STDIN Forwarding
For temporary input during container execution:
echo "input_data" | docker exec -i container_name java -jar app.jar
Method 3: Tailored for Background Services
When containers run in detached mode (-d):
# Create input file
echo "commands.txt" > input_sequence
# Attach STDIN source
docker run -d -i --name my_service \
--mount type=bind,source=$(pwd)/input_sequence,target=/input \
my-java-image < input_sequence
For Python automation using docker-py:
import docker
client = docker.from_env()
container = client.containers.get('my-container')
# Create exec instance with stdin
exec_id = container.exec_run(
"java -jar app.jar",
stdin=True,
socket=True
)
# Send input via websocket
sock = container.client.api.exec_start(
exec_id,
socket=True
)
sock.send("input_text\\n")
- Input validation at container boundary
- Timeout handling for hung processes
- Logging all STDIN transactions
- Resource limits on input size
When working with Docker containers running interactive processes that expect STDIN input, developers often need to automate input rather than attaching manually. The standard docker exec
approach doesn't work because it creates a new process rather than connecting to the existing one's STDIN.
Method 1: Using Named Pipes
Create a named pipe and attach it to the container:
mkfifo /tmp/container_input
docker run -it -v /tmp/container_input:/input my_image sh -c 'cat /input | java -jar myapp.jar'
Then send input from another terminal:
echo "your_input" > /tmp/container_input
Method 2: Direct Process Attachment
For containers already running with -it
:
# Get the container's PID
CONTAINER_PID=$(docker inspect --format '{{.State.Pid}}' container_name)
# Send input to the process
echo "input_text" | nsenter --target $CONTAINER_PID --mount --uts --ipc --net --pid
Method 3: Using Docker Exec with Process Substitution
For bash environments:
docker exec -i container_name bash -c 'cat > /proc/1/fd/0' < <(echo "your_input")
For a Java program reading from System.in:
# Start container with STDIN handling
docker run -it --name java_app my_java_image java -jar /app.jar
# In another terminal, send input
echo -e "first_command\nsecond_command" | docker attach --no-stdin java_app
- Always test input handling with simple commands first
- For production systems, consider implementing proper APIs rather than STDIN
- Remember that STDIN handling may differ between shell and direct process execution
- For complex interactions, expect/awk scripts might be more reliable