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
withcopytruncate
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