How to Redirect File/Syslog to stdout in Docker for 12-Factor App Compliance


3 views

When containerizing legacy applications that write logs to files or syslog, we face a fundamental mismatch with the 12-factor logging principle which states applications should write unbuffered output to stdout/stderr. Docker's logging drivers (json-file, journald, fluentd etc.) are designed to capture these streams.

Here are three battle-tested approaches:

1. Tail + stdout Redirection

# Dockerfile
CMD ["sh", "-c", "your_app > /proc/1/fd/1 2>/proc/1/fd/2 & tail -f /dev/null"]

Or for syslog:

CMD ["sh", "-c", "syslog-ng -F > /proc/1/fd/1 2>/proc/1/fd/2 & your_app"]

2. Named Pipe Technique

# Entrypoint script
mkfifo /tmp/logpipe
chmod 0666 /tmp/logpipe
cat /proc/1/fd/1 &

# Configure app to write to /tmp/logpipe
exec your_app --log-file=/tmp/logpipe

3. Rsyslog Forwarding

# /etc/rsyslog.conf
module(load="imfile" PollingInterval="1")
input(type="imfile" File="/var/log/app.log" Tag="myapp")
*.* /dev/stdout

# Docker run command
docker run -v /path/to/app.log:/var/log/app.log ...

For high-volume logs:

  • Use logrotate with copytruncate when tailing files
  • Set appropriate buffer sizes in syslog configurations
  • Monitor file descriptor limits in long-running containers

If logs aren't appearing:

# Check stdout binding
ls -l /proc/1/fd/{1,2}

# Verify Docker logging driver
docker inspect --format '{{.HostConfig.LogConfig.Type}}' container_name

When containerizing applications that weren't designed for cloud-native environments, we often encounter logging systems that write exclusively to files or syslog. This becomes problematic when deploying in Docker where stdout/stderr is the expected logging channel.

Container orchestration systems (Kubernetes, Docker Swarm, etc.) are designed to collect logs from stdout/stderr. Filesystem logs disappear when containers terminate, making stdout the only reliable logging channel for ephemeral containers.

Here are several approaches to redirect logs to stdout:

1. Using Tail in your Dockerfile

FROM your-base-image
RUN mkdir -p /var/log/app
CMD your-app-command &> /var/log/app/app.log && tail -f /var/log/app/app.log

2. Creating a Symlink to /dev/stdout

RUN ln -sf /dev/stdout /var/log/app.log

3. Using a Log Forwarder

For complex applications, consider running a lightweight log forwarder like busybox:

FROM your-base-image
RUN apk add --no-cache busybox
CMD your-app-command &> /var/log/app.log & \
    busybox syslogd -n -O /var/log/app.log

For applications that must have actual files:

RUN mkfifo /var/log/app.log
CMD your-app-command > /var/log/app.log & \
    cat /var/log/app.log

For applications writing to multiple log files:

CMD your-app-command & \
    multitail /var/log/app/*.log
  • Be mindful of log rotation
  • Monitor log volume to prevent disk filling
  • Consider using dedicated logging sidecars in Kubernetes