Category: Docker Compose

  • Docker Compose Logs: The Complete Debugging Guide

    Docker Compose Logs: A Practical Guide to Debugging Multi-Container Apps

    Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.

    When a container silently dies or a service starts throwing errors at 2 AM, docker compose logs is usually the first command you reach for. It’s the fastest way to see what’s actually happening inside your stack without SSHing into individual containers or digging through log files scattered across the filesystem.

    If you’re running Compose stacks in production — whether that’s a media server setup, a CI runner, or a full application backend — understanding log output is non-negotiable. Let’s get into it.

    Why docker compose logs Matters

    Unlike docker logs, which only works on a single container, docker compose logs aggregates output from every service defined in your docker-compose.yml. This matters because most real-world failures aren’t isolated — a database connection timeout in your API service might actually be caused by the database container failing to start, and you won’t see that correlation unless you’re looking at both logs side by side.

    If you’re new to container orchestration in general, our Docker networking fundamentals guide is a good companion piece before diving deeper into log debugging.

    Basic Syntax and Usage

    The core command is straightforward:

    docker compose logs

    Run this from the directory containing your docker-compose.yml, and it dumps the combined stdout/stderr output from every running service, prefixed by service name and color-coded in your terminal.

    To target a single service:

    docker compose logs web

    To target multiple specific services:

    docker compose logs web db redis

    This is useful when you have a stack with 10+ services (common in microservice architectures) and only care about the ones involved in a specific request path.

    Following Logs in Real Time

    By default, docker compose logs prints everything and exits. To keep the stream open and watch new log lines as they arrive — similar to tail -f — add the -f or --follow flag:

    docker compose logs -f

    This is the flag you’ll use most often during active debugging sessions. Combine it with a service filter to watch just one component while you reproduce a bug:

    docker compose logs -f api

    Press Ctrl+C to stop following without stopping the containers themselves.

    Limiting Output with Tail

    On long-running production services, log history can be enormous. Dumping the entire history to your terminal is slow and mostly useless. Use --tail to limit output to the most recent N lines:

    docker compose logs --tail=100 api

    Combine --tail with --follow to get recent context plus a live stream:

    docker compose logs --tail=50 -f api db

    This pattern — recent history plus live tail — is the single most useful log-debugging habit you can build.

    Adding Timestamps

    By default, Compose logs don’t show timestamps, which makes it hard to correlate events across services or figure out how much time elapsed between two log lines. Add the -t or --timestamps flag:

    docker compose logs -t --tail=100 api

    Output looks like this:

    api_1  | 2026-07-02T14:22:01.123456789Z Starting server on port 3000
    api_1  | 2026-07-02T14:22:03.987654321Z Connected to database

    Timestamps are essential when you’re trying to line up an error in your app logs with a corresponding event in your reverse proxy or database logs.

    Filtering by Time Range

    If you know roughly when an incident occurred, you don’t need to scroll through hours of noise. Use --since and --until to bound the output:

    docker compose logs --since 2026-07-02T14:00:00 --until 2026-07-02T14:30:00 api

    You can also use relative durations:

    docker compose logs --since 30m api

    This pulls only logs from the last 30 minutes — extremely useful when triaging a fresh incident without wading through days of accumulated output.

    Disabling the Log Prefix

    When you’re only looking at one service and want cleaner output (for piping into grep or another tool), drop the service-name prefix with --no-log-prefix:

    docker compose logs --no-log-prefix api | grep ERROR

    This is handy when scripting log analysis or feeding output into external tools.

    Piping and Searching Logs

    docker compose logs output is just text, so standard Unix tools work fine on top of it. A few practical patterns:

  • Search for errors across all services: docker compose logs | grep -i error
  • Count occurrences of a specific warning: docker compose logs | grep -c "connection refused"
  • Save a snapshot for later analysis: docker compose logs --no-color > incident-2026-07-02.log
  • Watch only 500 errors in a web service: docker compose logs -f web | grep "500"
  • Combine tail and search for a fast triage loop: docker compose logs --tail=200 db | grep -i "deadlock"
  • These one-liners solve 90% of the ad-hoc debugging you’ll do day to day, without needing a dedicated log aggregation tool.

    Common Problems and How Logs Help Diagnose Them

    Container Restart Loops

    If a container keeps restarting, docker compose ps will show a high restart count, but docker compose logs tells you why. Run it without --tail truncation on a small window right after the crash:

    docker compose logs --since 5m --tail=200 worker

    Look for the last few lines before the process exits — that’s almost always where the actual error (missing environment variable, failed migration, out-of-memory kill) shows up.

    Silent Startup Failures

    Sometimes a service reports as “running” but isn’t actually healthy — for example, a database that’s accepting connections but hasn’t finished initializing. Following logs during startup catches this:

    docker compose up -d
    docker compose logs -f db

    Watch for the specific “ready to accept connections” message your database emits before assuming dependent services can connect.

    Cross-Service Correlation

    When your API returns a 500 error, you often need to see what the database or cache was doing at the exact same millisecond. Use timestamps and pull both services together:

    docker compose logs -t --since 10m api redis

    Having both streams interleaved by timestamp makes root-cause analysis dramatically faster than tailing them in separate terminal windows.

    For a deeper dive into container health checks that complement log-based debugging, see our Docker health check configuration guide.

    Beyond docker compose logs: When to Use a Real Logging Stack

    The built-in logging command is great for local development and quick production triage, but it has real limits: no persistent storage past the log driver’s retention, no full-text search across weeks of history, and no alerting. Once you’re running more than a handful of services, it’s worth shipping logs to a dedicated platform.

    For teams that don’t want to run their own Elasticsearch or Loki stack, a hosted monitoring and log management service removes the operational overhead. BetterStack offers log management and uptime monitoring that integrates cleanly with Docker Compose setups via simple log-driver configuration, so you get searchable, retained logs and alerting without babysitting another piece of infrastructure.

    If you’re hosting your Compose stack yourself, the underlying VPS matters too — slow disk I/O can bottleneck log writes on high-throughput services. Providers like DigitalOcean and Hetzner both offer NVMe-backed instances that hold up well under heavy container logging workloads, and either is a solid choice for a self-managed Compose deployment.

    Configuring the Logging Driver

    By default, Compose uses the json-file driver, which can grow unbounded if you don’t set limits. Add size and rotation limits directly in your docker-compose.yml:

    services:
      api:
        image: myapp:latest
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: "3"

    This caps each log file at 10MB and keeps a maximum of 3 rotated files per container, preventing a chatty service from filling your disk.

    Quick Reference: Useful Flags

  • -f, --follow — stream logs continuously
  • --tail=N — show only the last N lines
  • -t, --timestamps — prepend ISO 8601 timestamps
  • --since / --until — bound output by time
  • --no-log-prefix — remove service name prefix
  • --no-color — strip ANSI color codes (useful when redirecting to a file)
  • Memorize --tail and -f first — they cover the majority of day-to-day debugging. Add -t and --since once you’re troubleshooting timing-sensitive issues across multiple services.

    Recommended: Ready to put this into practice? DigitalOcean is a tool we use for exactly this, and we have a real, disclosed affiliate relationship with them.

    FAQ

    Q: What’s the difference between docker logs and docker compose logs?
    A: docker logs <container> targets a single container by name or ID. docker compose logs operates on an entire Compose project, aggregating and interleaving output from all defined services (or a filtered subset) in one command.

    Q: Why don’t I see any output when I run docker compose logs?
    A: This usually means the containers aren’t running, or they’re writing logs to a file inside the container instead of stdout/stderr. Docker only captures stdout/stderr by default — check your app’s logging configuration to make sure it logs to the console, not a file.

    Q: How do I clear or reset the logs for a service?
    A: Compose doesn’t have a built-in “clear logs” command. You typically need to either restart the container (which starts a fresh log file depending on your driver) or manually truncate the underlying log file on the host if you have access to it.

    Q: Can I export logs to a file for sharing with a teammate?
    A: Yes. Run docker compose logs --no-color > output.log to save a clean, ANSI-free text file that’s easy to share or attach to a ticket.

    Q: Does --tail work with --follow at the same time?
    A: Yes, and it’s a very common combination. docker compose logs --tail=100 -f api shows the last 100 lines immediately, then continues streaming new lines as they arrive.

    Q: Why are my logs missing timestamps even in the raw JSON log file?
    A: The json-file driver does store timestamps internally, but docker compose logs only displays them when you pass -t/--timestamps. Without that flag, Compose strips them from the terminal output for readability.

    Wrapping Up

    docker compose logs is deceptively simple but covers most of what you need for day-to-day container debugging: filtering by service, following in real time, bounding by time range, and piping into standard Unix tools for search. Combine it with sensible logging-driver limits and, once your stack grows, a proper log aggregation service to avoid losing critical history.

    For related deployment topics, check out our Docker Compose production checklist to make sure your logging setup fits into a broader operational strategy.

  • Docker Compose Down: Full Guide to Stopping Stacks

    Docker Compose Down: The Complete Guide to Stopping and Cleaning Up Your Stack

    Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.

    If you run multi-container applications, you already know docker compose up is the easy part. The command that actually trips people up — and occasionally wipes out data they didn’t mean to lose — is docker compose down. It looks simple on the surface, but the flags you attach to it determine whether you get a clean, reversible stop or a full teardown that deletes volumes, networks, and images.

    This guide covers exactly what docker compose down does under the hood, every major flag, how it differs from docker compose stop, and the mistakes that cause the most support tickets and Stack Overflow posts. We’ll also touch on how this fits into a broader DevOps deployment workflow if you’re managing production stacks.

    What Does docker compose down Actually Do?

    When you run:

    docker compose down

    Compose does the following, in order:

  • Stops all running containers defined in your docker-compose.yml
  • Removes those containers (not just stops them — they’re gone)
  • Removes any networks created by Compose for the project
  • Leaves named volumes and images untouched by default
  • This is the critical distinction from docker compose stop, which only pauses containers without deleting them. If you want to preserve container state for a quick restart, stop is the safer choice. If you want a clean slate — containers and networks gone, but data intact — down is what you want.

    # Just pause everything, keep containers on disk
    docker compose stop
    
    # Stop AND remove containers + networks
    docker compose down

    Why Containers Get Removed But Volumes Don’t

    Docker’s design philosophy treats containers as disposable and volumes as durable. Containers hold your application process; volumes hold your data (database files, uploaded media, logs). docker compose down respects that separation by default — it tears down the disposable layer and leaves the durable layer alone unless you explicitly tell it not to.

    This matters enormously if you’re running something like PostgreSQL, MySQL, or a media server with persistent libraries. Running plain docker compose down and back up with docker compose up -d will not touch your database contents, because the volume survives the teardown.

    The Flags That Actually Matter

    -v / --volumes: Deleting Named and Anonymous Volumes

    This is the flag that causes the most accidental data loss:

    docker compose down -v

    Adding -v removes named volumes declared in the volumes: section of your compose file, along with anonymous volumes attached to containers. If your Postgres data lives in a named volume like pgdata:, this command deletes it permanently. There’s no confirmation prompt — it just happens.

    Rule of thumb: never run docker compose down -v on a production stack unless you have a verified backup. Test this in a scratch environment first, and consider backing up with a tool like Restic or a scheduled pg_dump before any teardown that touches volumes.

    --rmi: Removing Images Too

    If you also want to reclaim disk space by deleting images built or pulled for the stack:

    docker compose down --rmi all

    Options here are all (remove every image used by any service) or local (only remove images that don’t have a custom tag, i.e., ones Compose built itself). This is useful in CI pipelines where you rebuild from scratch every run, but it’s overkill for a local dev loop where rebuilding images repeatedly wastes time and bandwidth.

    --remove-orphans: Cleaning Up Renamed or Deleted Services

    When you remove a service from your docker-compose.yml but its container is still running from a previous up, Compose calls it an “orphan.” By default, down won’t touch containers it doesn’t recognize from the current file. Force it with:

    docker compose down --remove-orphans

    This is especially common after refactoring a compose file — renaming a service from web to frontend, for example, leaves the old web container orphaned and still consuming resources.

    -t / --timeout: Controlling Shutdown Grace Period

    By default, Compose sends SIGTERM and waits 10 seconds before force-killing with SIGKILL. For services that need longer to flush writes or close connections gracefully (databases, message queues), increase the timeout:

    docker compose down -t 30

    For stacks with fast-shutdown stateless services, you can shrink this to speed up CI teardown:

    docker compose down -t 2

    Combining Flags for a Full Reset

    When you genuinely want to nuke everything — containers, networks, volumes, images, and orphans — in a disposable dev or CI environment:

    docker compose down -v --rmi all --remove-orphans

    This is the command CI pipelines commonly run at the end of an integration test job to guarantee no leftover state pollutes the next run.

    Common Scenarios and How to Handle Them

    Scenario 1: Restarting a Stack Without Losing Data

    docker compose down
    docker compose up -d

    Safe. Networks and containers are recreated fresh, but named volumes persist.

    Scenario 2: Wiping a Dev Environment Completely

    docker compose down -v --remove-orphans

    Use this when your local Postgres or Redis data has gotten into a weird state and you’d rather start clean than debug it.

    Scenario 3: Targeting a Specific Project When You Have Multiple Stacks

    If you run several Compose projects on the same host, specify the project name explicitly to avoid tearing down the wrong stack:

    docker compose -p myproject down

    This matters a lot on shared VPS environments where multiple teams or apps run side by side — mixing up project names is an easy way to take down someone else’s containers. If you’re managing several stacks on a single VPS, it’s worth reading up on Docker network isolation strategies to keep projects from stepping on each other.

    Scenario 4: down Hangs or Times Out

    If a container refuses to stop gracefully within the timeout window, Compose force-kills it, but you might see:

    ERROR: for web  Container did not stop within 10 seconds

    Fix it by increasing the timeout or checking whether your app’s entrypoint script is trapping SIGTERM correctly. Some Node.js and Python apps swallow the signal without exiting, which forces the timeout every time. Adding proper signal handling in your entrypoint (or using tini) usually resolves this. For a deep dive on signal handling inside containers, the official Docker docs on stopping containers are worth reading.

    docker compose down vs Related Commands

  • docker compose stop — pauses containers, keeps them on disk for a fast restart
  • docker compose down — stops and removes containers + networks, keeps volumes/images by default
  • docker compose rm — removes stopped containers without touching networks (rarely needed once you use down)
  • docker compose kill — force-kills containers immediately, skipping graceful shutdown entirely
  • If your goal is a quick pause-and-resume during development, stop plus start is faster since it skips network and container recreation. Reserve down for when you actually want to reset the project’s runtime state.

    Automating Safe Teardowns in Scripts

    If you’re scripting deployments or CI jobs, wrap the teardown in something explicit rather than relying on defaults:

    #!/usr/bin/env bash
    set -euo pipefail
    
    echo "Tearing down stack (volumes preserved)..."
    docker compose down --remove-orphans -t 15
    
    echo "Done."

    Keeping volume deletion out of your default script prevents a copy-paste accident from wiping production data. Make volume deletion a deliberate, separate command that requires a human to type it out.

    Hosting Considerations for Compose Stacks

    Where you host your Compose stack affects how forgiving these commands are. On a resource-constrained VPS, an orphaned container silently eating RAM can push you into swap and degrade every other service on the box. If you’re outgrowing a budget VPS and need predictable CPU/RAM for Docker workloads, providers like DigitalOcean offer straightforward droplet sizing built for exactly this kind of container hosting, and Hetzner is a solid budget option for dev/staging stacks where you’re tearing things down and rebuilding often. For monitoring container health so a bad down/up cycle doesn’t go unnoticed, BetterStack gives you uptime and log monitoring without much setup overhead.

    If your stack sits behind a domain and you want to keep DNS and CDN caching predictable while you restart backend containers, Cloudflare is worth having in front of anything public-facing — it also means a down/up cycle doesn’t immediately expose a connection-refused error to visitors while containers spin back up.

    For teams optimizing how these guides and docs get found organically, tracking keyword rankings with a tool like SE Ranking helps you see which Docker/DevOps topics are actually driving traffic before you invest more writing time in them.

    Checking What Would Be Removed Before Running It

    Compose doesn’t have a true dry-run flag for down, but you can inspect what’s currently active before tearing anything down:

    docker compose ps
    docker compose config --services
    docker volume ls

    Running these three commands first tells you exactly which containers, services, and volumes exist under the current project name, so down -v doesn’t surprise you.

    Troubleshooting Checklist

  • Network still exists after down — another running project may share the network name; check with docker network ls
  • Volume wasn’t deleted despite -v — the volume might be marked external: true in your compose file, which Compose deliberately never deletes
  • “No such service” errors — you’re likely running down from a directory without the matching docker-compose.yml, or with a mismatched -f file path
  • Containers reappear after down — a process manager like systemd or a restart: always policy combined with an external supervisor may be recreating them; check for a wrapping service definition
  • If you’re still getting familiar with the broader Compose command set beyond teardown, our guide to essential Docker Compose commands covers up, logs, exec, and ps in the same practical style.

    Recommended: Ready to put this into practice? SE Ranking is a tool we use for exactly this, and we have a real, disclosed affiliate relationship with them.

    FAQ

    Does docker compose down delete my data?
    Not by default. It removes containers and networks but preserves named volumes. Data loss only happens if you explicitly add the -v or --volumes flag.

    What’s the difference between docker compose down and docker compose stop?
    stop pauses containers without removing them, so a subsequent start is fast. down removes the containers and networks entirely, requiring Compose to recreate them on the next up.

    How do I remove only some services instead of the whole stack?
    docker compose down doesn’t support targeting individual services — it’s all-or-nothing for the project. To stop a single service without touching the rest, use docker compose stop <service_name> or docker compose rm -s -f <service_name>.

    Why didn’t my volume get deleted even with -v?
    If the volume is declared as external: true in your compose file, Docker treats it as managed outside the project’s lifecycle and never deletes it automatically, regardless of flags.

    Is it safe to run docker compose down -v in production?
    Only if you have a verified, tested backup of every volume involved. There is no undo. Many teams explicitly ban -v from production deployment scripts and require it to be run manually with confirmation.

    How do I remove orphaned containers left over from an old compose file?
    Run docker compose down --remove-orphans, which detects and removes containers that no longer match any service defined in the current docker-compose.yml.

    Wrapping Up

    docker compose down is safer than people assume once you understand its default behavior: containers and networks go, volumes and images stay. The danger comes entirely from the extra flags — -v and --rmi all — which turn a routine teardown into a destructive one. Keep those flags out of your default scripts, reserve them for deliberate resets, and always check docker volume ls before you run anything with -v against a stack that matters.

    Get comfortable with stop for quick pauses, down for clean resets, and down -v --remove-orphans --rmi all for full nukes in disposable environments, and you’ll rarely be surprised by what Compose does on teardown.

  • Redis Docker Compose: The Complete Setup Guide

    Redis Docker Compose: The Complete Setup and Caching Guide

    Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.

    Adding a cache layer used to mean provisioning a separate service, wiring up network rules, and hoping the versions matched. A Redis Docker Compose setup collapses all of that into a few lines of YAML: one service block, one shared network, and Redis is reachable from every other container in your stack by name.

    This guide walks through a production-ready Redis Docker Compose configuration, how to persist data across restarts, how to secure the connection with a password, and the mistakes that cause the most confusion when people wire Redis into an existing Postgres Docker Compose stack.

    What a Redis Docker Compose Setup Actually Gives You

    At its simplest, a Redis Docker Compose service is just an image reference and a port:

    yaml
    services:
    cache:
    image: redis:7-alpine
    ports:
    - "6379:6379"
    `

    That's enough to get Redis running, but a real Redis Docker Compose stack needs three more things most tutorials skip: a named volume for persistence, a password, and a healthcheck so dependent services don't start before Redis is actually ready to accept connections.

    A Complete Redis Docker Compose Configuration

    Here's a realistic Redis Docker Compose file for an API that uses Redis for session storage and caching, alongside Postgres for durable data:

    `yaml
    services:
    api:
    build: .
    environment:
    - REDIS_URL=redis://:$REDIS_PASSWORD@cache:6379
    depends_on:
    cache:
    condition: service_healthy

    cache:
    image: redis:7-alpine
    command: redis-server --requirepass $REDIS_PASSWORD --appendonly yes
    volumes:
    - redis_data:/data
    healthcheck:
    test: [CMD, redis-cli, --raw, -a, $REDIS_PASSWORD, ping]

    volumes:
    redis_data:
    `

    Every other service resolves the cache by its Compose service name, cache:6379, because Compose gives the project its own internal bridge network automatically. That's the core advantage of a Redis Docker Compose deployment over running docker run redis by hand.

    Why the Healthcheck Matters

    Without a healthcheck, depends_on only waits for the Redis container to start, not for the Redis server inside it to finish loading. The condition: service_healthy clause blocks the api service until redis-cli ping actually succeeds.

    Persisting Redis Data with Docker Compose Volumes

    By default, Redis is an in-memory store, restart the container and everything is gone. A Redis Docker Compose setup that cares about surviving restarts needs a named volume plus one of Redis's two persistence modes.

  • RDB snapshotting: periodic point-in-time dumps, smaller files, faster restarts, but you can lose the last few minutes of writes
  • AOF append-only file: logs every write operation, safer, larger on disk, slightly slower recovery on huge datasets
  • Checking That Persistence Is Actually Working

    `bash
    docker compose exec cache redis-cli -a $REDIS_PASSWORD set healthcheck ok
    docker compose down
    docker compose up -d
    docker compose exec cache redis-cli -a $REDIS_PASSWORD get healthcheck
    `

    If the second get returns ok, your Redis Docker Compose volume is correctly mounted and persistence is active.

    Securing a Redis Docker Compose Service

    Redis binds with no authentication by default, which is fine on an isolated Compose network but dangerous the moment a port gets accidentally exposed to the host or the internet.

  • Set –requirepass so every client needs a password, injected via a .env file
  • Drop the ports: mapping entirely unless you need to reach Redis from outside the Compose network
  • Common Redis Docker Compose Patterns

  • Session store: Express, Django, and Rails all have first-party Redis session adapters
  • Rate limiting: token-bucket limiters backed by Redis's atomic INCR and EXPIRE commands
  • Job queues: libraries like BullMQ or Celery use Redis as the broker between web and worker processes
  • Full-page and query caching: cache expensive database results with a TTL
  • Troubleshooting a Redis Docker Compose Stack

  • Connection refused from the app container: add the healthcheck shown above instead of a fixed sleep
  • NOAUTH Authentication required: confirm the connection string includes the password segment
  • Data disappears after docker compose down: check the volumes: mapping, or you ran docker compose down -v
  • High memory usage: set maxmemory and maxmemory-policy allkeys-lru in the command: block
  • Hosting a Redis Docker Compose Stack in Production

    Redis is memory-hungry by design. If you're outgrowing a budget droplet, DigitalOcean makes it easy to resize RAM, and Hetzner is a solid budget option. BetterStack gives you uptime monitoring for a wedged Redis container, and Cloudflare keeps DNS and TLS predictable in front of your API.

    Once your Redis Docker Compose service is stable, docker compose down is the safe way to stop it without touching the redis_data volume. Our guide to Docker Compose environment variables covers .env file precedence in more depth.

    Monitoring a Redis Docker Compose Service

    Once a Redis Docker Compose stack is running in production, memory pressure is the metric that matters most, since Redis keeps its entire working set in RAM. Two commands make quick diagnostics easy:

    `bash
    docker compose exec cache redis-cli -a $REDIS_PASSWORD info memory
    docker compose exec cache redis-cli -a $REDIS_PASSWORD info stats
    `

    The info memory output shows used_memory_human and maxmemory_human; if the two are converging, it's time to either raise the container's memory limit or tighten your maxmemory-policy. The info stats output includes keyspace_hits and keyspace_misses — a rising miss ratio over time usually means your cache TTLs are too short or your working set has outgrown the box.

    Setting Resource Limits in the Compose File

    A Redis Docker Compose service without a memory ceiling can consume all available host RAM during a traffic spike, starving the database and app containers sharing the same VPS. Pin it explicitly:

    `yaml
    cache:
    image: redis:7-alpine
    deploy:
    resources:
    limits:
    memory: 512M
    `

    Combined with maxmemory 400mb inside the command: block, this keeps a single Redis Docker Compose service from taking down its neighbors when key eviction alone isn't fast enough.

    Redis Docker Compose with Multiple Logical Databases

    Redis ships with 16 numbered logical databases (0-15) inside a single instance, selectable with SELECT n from redis-cli. For a small Redis Docker Compose stack running a cache and a job queue side by side, putting each on its own numbered database avoids a FLUSHDB in one context accidentally wiping the other. For anything beyond a handful of services, most teams prefer key prefixing (session:, queue:, cache:) over numbered databases, since prefixes show up clearly in monitoring dashboards while a bare database number does not.

    Recommended: Want to explore DigitalOcean yourself? DigitalOcean is a direct vendor link (not an affiliate/tracked link).

    FAQ

    Do I need a separate Dockerfile for Redis in a Docker Compose stack?
    No. Use the official
    redis:7-alpine image directly in your Redis Docker Compose file — you only need a custom Dockerfile if you're baking in custom modules that can't be passed via command: flags.

    Does Redis Docker Compose data survive docker compose down?
    Yes, as long as you're using a named volume and skip the
    -v flag. Plain docker compose down removes containers and networks but leaves volumes, and therefore your Redis data, intact.

    What's the difference between RDB and AOF persistence in a Redis Docker Compose setup?
    RDB snapshots recover faster but can lose a few minutes of recent writes; AOF logs every write and is safer but slightly slower to replay on restart. Many production Redis Docker Compose stacks enable both for defense in depth.

    Can multiple services share one Redis Docker Compose instance?
    Yes — use separate numbered Redis databases or key prefixing per service, so a cache flush in one service doesn't wipe session data for another.

    Is it safe to run one Redis Docker Compose instance for both caching and a job queue?
    Yes, as long as you isolate them with separate logical databases or key prefixes and set eviction policies that only apply to cache keys — you don't want
    allkeys-lru evicting queue jobs still waiting to be processed.

    How much RAM does a small Redis Docker Compose service actually need?
    For a low-traffic app using Redis purely for sessions and light caching, 128-256MB is typically enough; job queues holding large payloads need considerably more, and
    info memory is the fastest way to check actual usage rather than guessing.

    Wrapping Up

    A Redis Docker Compose setup is a handful of YAML lines once you know the pieces that matter: a named volume for persistence, –requirepass plus a .env` file for security, a healthcheck so dependent services wait for Redis to be truly ready, and a memory limit so one noisy cache doesn’t starve the rest of the stack. Get those right and Redis becomes a boring, reliable part of your stack instead of a source of cold-start races and vanished cache data.