Many developers encounter this frustrating scenario: you've set up SSHD in a Docker container with the -D
flag, but docker logs
shows nothing. This behavior occurs because:
- SSHD with
-D
runs in foreground but doesn't write to stdout/stderr by default - Docker captures container logs from these standard streams
- The logging backend (journald/json-file) makes no difference for this particular issue
The correct approach requires adding the -e
flag to make SSHD output logs to stderr:
FROM alpine:latest
RUN apk add --no-cache openssh-server \
&& mkdir /var/run/sshd \
&& ssh-keygen -A
CMD ["/usr/sbin/sshd", "-D", "-e"]
For more advanced logging requirements, consider these approaches:
1. Direct Log File Access
# In Dockerfile
RUN mkdir -p /var/log && touch /var/log/sshd.log
CMD ["sh", "-c", "/usr/sbin/sshd -D -E /var/log/sshd.log"]
# To view logs:
docker exec -it container-name tail -f /var/log/sshd.log
2. Syslog Forwarding
# Install syslog daemon
RUN apk add --no-cache rsyslog
# Configure SSHD to use syslog
CMD ["sh", "-c", "rsyslogd & /usr/sbin/sshd -D -e"]
If logs still don't appear:
- Verify the container is actually running:
docker ps
- Check for immediate exits:
docker inspect --format='{{.State.ExitCode}}' container-name
- Test with simpler commands first:
CMD ["sh", "-c", "echo 'test' && /usr/sbin/sshd -D -e"]
For production environments:
# Use a proper init system to manage processes
RUN apk add --no-cache openrc
CMD ["/sbin/init", "sshd -D -e"]
Remember that running SSHD in containers has security implications. Consider alternatives like docker exec
for most use cases.
When running SSHd in a Docker container with Alpine Linux, a common frustration is that logs don't appear through docker logs
command. This happens because by default, SSHd logs to syslog rather than stdout/stderr.
# Typical Dockerfile that won't show logs
FROM alpine:latest
RUN apk add --no-cache openssh-server \
&& mkdir /var/run/sshd \
&& ssh-keygen -A
CMD ["/usr/sbin/sshd", "-D"]
The solution lies in SSHd's -e
flag, which forces logging to stderr:
# Working Dockerfile with visible logs
FROM alpine:latest
RUN apk add --no-cache openssh-server \
&& mkdir /var/run/sshd \
&& ssh-keygen -A
CMD ["/usr/sbin/sshd", "-D", "-e"]
While -D
keeps SSHd in foreground mode (necessary for Docker), -e
ensures logs go to stderr. Testing shows:
docker run -d --name sshd-container sshd-image
docker logs sshd-container
# Now shows:
# Server listening on 0.0.0.0 port 22.
# Server listening on :: port 22.
For more complex logging needs, consider these options:
# 1. Redirect syslog to stdout
CMD ["sh", "-c", "/usr/sbin/sshd -D | logger -t sshd"]
# 2. Use custom logging configuration
RUN echo "SyslogFacility DAEMON" >> /etc/ssh/sshd_config
When using journald driver, verify logs with:
journalctl -u docker CONTAINER_NAME=sshd-container
Remember that journald may add its own timestamp and metadata fields to log entries.
For production environments, consider:
- Adding log rotation (logrotate inside container)
- Using centralized logging (Fluentd, ELK stack)
- Implementing log level control via sshd_config
# Example for log level control
RUN echo "LogLevel VERBOSE" >> /etc/ssh/sshd_config