Skip to main content
Docker·9 min read

Docker Container Logs Disappearing? Debugging Containers That Already Crashed

Master Docker container log management for debugging production issues. Covers docker logs, log drivers, filtering by time, JSON structured logging, and integrating with log aggregation systems.

DT

DevOps Engineer & Technical Writer

The Problem

A container is restarting every 30 seconds. The health check is failing. The application throws errors but you cannot tell if it is a code bug, missing environment variable, or connectivity issue. Docker logs are your first and fastest debugging tool — if you know how to extract the right information.

Container Logging Architecture Container stdout stderr Docker Logging Driver Configurable backend json-file Default driver fluentd Log forwarder syslog System logging awslogs CloudWatch Centralized Storage ELK / CloudWatch

Viewing Container Logs

docker logs my-container                           # All logs

docker logs -f my-container # Follow real-time

docker logs --tail 100 my-container # Last 100 lines

docker logs -t my-container # With timestamps

docker logs --since 30m my-container # Last 30 minutes

docker logs --since 1h my-container # Last hour

docker logs --since 2024-01-15T10:00:00 --until 2024-01-15T10:30:00 my-container

docker logs -f --tail 50 my-container # Follow from last 50

Docker Compose logs

docker compose logs                                # All services

docker compose logs api # Specific service

docker compose logs -f api worker # Follow multiple

docker compose logs --tail 50 -t # Last 50 with timestamps

docker compose logs --since 30m api # Recent logs

Filtering and Searching

docker logs my-container 2>&1 | grep -i "error"

docker logs my-container 2>&1 | grep -B3 -A3 "Exception"

docker logs my-container 2>&1 | grep -c "ERROR"

docker logs my-container 2>&1 | grep "ERROR" | sort -u

docker logs my-container 2>&1 | jq -r 'select(.level == "error")'

docker logs -f my-container 2>&1 | grep --line-buffered "ERROR"

Note: 2>&1 combines stdout and stderr for complete search coverage.

Debugging Container Startup Issues

Container exits immediately

# Check exit code

docker inspect my-container --format='{{.State.ExitCode}}'

docker inspect my-container --format='{{json .State}}' | jq

docker logs my-container

# Common exit codes:

# 0 — Normal exit

# 1 — Application error

# 137 — SIGKILL (OOM killed or docker kill)

# 139 — SIGSEGV (segmentation fault)

# 143 — SIGTERM (graceful shutdown)

Container keeps restarting

docker inspect my-container --format='{{.RestartCount}}'

docker inspect my-container --format='{{.State.StartedAt}}'

docker logs --since 2m my-container

docker events --filter container=my-container --since 10m

Exec into running container

docker exec -it my-container /bin/bash

docker exec -it my-container /bin/sh # Alpine images

docker exec my-container env | sort # Check env vars

docker exec my-container curl -s http://db-host:5432

docker exec my-container nslookup redis-service

docker exec my-container cat /app/config/application.yml

Resource inspection

docker stats my-container                   # Live stats

docker stats --no-stream my-container # One-shot

docker inspect my-container --format='{{.State.OOMKilled}}'

Log Drivers

Check current driver

docker info --format '{{.LoggingDriver}}'

docker inspect my-container --format='{{.HostConfig.LogConfig.Type}}'

JSON file with rotation

docker run -d \

--log-driver json-file \

--log-opt max-size=10m \

--log-opt max-file=5 \

--name api myapp:latest

Docker Compose configuration

services:

api:

image: myapp:latest

logging:

driver: json-file

options:

max-size: "10m"

max-file: "5"

tag: "{{.Name}}/{{.ID}}"

Other log drivers

# AWS CloudWatch

logging:

driver: awslogs

options:

awslogs-region: us-east-1

awslogs-group: /ecs/myapp

awslogs-stream-prefix: api

# Fluentd

logging:

driver: fluentd

options:

fluentd-address: localhost:24224

tag: docker.myapp

Structured JSON Logging

docker logs my-container 2>&1 | jq '.'

docker logs my-container 2>&1 | jq 'select(.level == "error")'

docker logs my-container 2>&1 | jq -r '[.timestamp, .level, .message] | @tsv'

# Count errors per endpoint

docker logs my-container 2>&1 | \

jq -r 'select(.level == "error") | .path' | sort | uniq -c | sort -rn

# Filter 500s from last hour

docker logs --since 1h my-container 2>&1 | jq 'select(.status_code >= 500)'

Log Management for Production

Global rotation in daemon.json

{

"log-driver": "json-file",

"log-opts": {

"max-size": "10m",

"max-file": "3"

}

}

Finding and managing log files

docker inspect my-container --format='{{.LogPath}}'

du -sh /var/lib/docker/containers/*/

find /var/lib/docker/containers -name "*-json.log" -size +100M

# Emergency truncation

truncate -s 0 $(docker inspect my-container --format='{{.LogPath}}')

Docker Compose Debugging Workflow

# 1. Check container status

docker compose ps

# 2. Check logs

docker compose logs --tail 50 api

# 3. Test connectivity

docker compose exec api curl -s http://postgres:5432

# 4. Verify environment

docker compose exec api env | grep DB_

# 5. View resolved config

docker compose config

# 6. Restart service

docker compose restart api

# 7. Rebuild and restart

docker compose up -d --build api

Common Mistakes

  • Not using 2>&1 when piping — Docker sends stdout and stderr separately. Without combining, grep misses error output.
  • No log rotation configured — Default has no size limit. A chatty container fills the disk. Always set max-size and max-file.
  • Using docker logs with non-json-file driversdocker logs only works with json-file and journald. With syslog or fluentd, logs go directly to those systems.
  • Ignoring container exit codes — Exit code 137 means OOM kill. Exit code 1 means application error. The code narrows your investigation.
  • Not checking docker events — Events show kills, restarts, and OOM kills — information not in application logs.
  • Logging sensitive data — Passwords and tokens in logs are a security risk. Audit what your application logs.
  • Quick Reference

    TaskCommand
    View logs<code class="inline-code">docker logs container</code>
    Follow logs<code class="inline-code">docker logs -f container</code>
    Last N lines<code class="inline-code">docker logs --tail 100 container</code>
    Since time<code class="inline-code">docker logs --since 30m container</code>
    With timestamps<code class="inline-code">docker logs -t container</code>
    Search logs<code class="inline-code">docker logs container 2&gt;&amp;1 \grep &quot;ERROR&quot;</code>
    Exit code<code class="inline-code">docker inspect container --format=&#39;{{.State.ExitCode}}&#39;</code>
    OOM check<code class="inline-code">docker inspect container --format=&#39;{{.State.OOMKilled}}&#39;</code>
    Log file path<code class="inline-code">docker inspect container --format=&#39;{{.LogPath}}&#39;</code>
    Resource stats<code class="inline-code">docker stats container</code>
    Compose logs<code class="inline-code">docker compose logs -f service</code>
    Truncate logs<code class="inline-code">truncate -s 0 $(docker inspect container --format=&#39;{{.LogPath}}&#39;)</code>

    Summary

    Docker logs are your fastest path to diagnosing container issues. Use --since and --tail to narrow the window, pipe through grep and jq for filtering, and always check exit codes and OOM status. Configure log rotation on every production deployment and use structured JSON logging for efficient parsing.

    ---

    Frequently Asked Questions

    How do I view Docker container logs?

    Use docker logs <container-name> for all logs or docker logs --tail 100 <container-name> for the last 100 lines. Add -f to follow logs in real-time (like tail -f). For containers that have crashed, logs are still available until the container is removed. Use --since 1h to filter by time.

    Why are my Docker container logs empty?

    The application inside the container must write to stdout/stderr for Docker to capture logs. If the application writes to a file instead, Docker logs will be empty. Fix this by configuring your application to log to stdout, or use a symlink like ln -sf /dev/stdout /var/log/app.log in your Dockerfile. Some official images do this by default.

    How do I configure Docker log rotation?

    Set log rotation in Docker's daemon.json with "log-opts": {"max-size": "10m", "max-file": "3"} to limit each container to 3 files of 10MB. Without rotation, logs grow unbounded and can fill your disk. You can also set these per-container with --log-opt flags in docker run or in your compose file under logging:.

    What is the difference between docker logs and docker attach?

    docker logs shows historical output (stdout/stderr) captured by the logging driver without connecting to the container. docker attach connects your terminal to the container's running process and shows live output, but stdin is also connected which means Ctrl+C can stop the container. Use docker logs -f for safe live tailing without risk of stopping the container.

    How do I debug a container that keeps crashing?

    Use docker logs <container> to see error output before the crash. If the container exits too fast, override the entrypoint with docker run --entrypoint /bin/sh <image> to get a shell for investigation. Check exit codes with docker inspect --format='{{.State.ExitCode}}' <container> — exit code 137 means OOM killed, 1 means application error.

    ---