You add the official redis image to a Compose file, and your app logs Could not connect to Redis at 127.0.0.1:6379: Connection refused. Or it gets DENIED Redis is running in protected mode, or NOAUTH Authentication required. Or Redis works until its first snapshot, and then every write fails with MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk.
This guide reproduces each of those errors with redis:8.10.3 in Docker Compose and fixes them. Every error message and log line below comes from that lab run on October 31, 2026, when redis:latest pulled the same 8.10.3 image. These errors are common. The Stack Overflow question MISCONF Redis is configured to save RDB snapshots had 646,097 views that day, Connecting to Redis running in Docker Container from Host machine had 306,329, and the image repo issue Set password and other options via ENV variable has 53 comments.
The short version:
- From another container,
localhostis that container. Connect to the Compose service name, for exampleredis. - A mounted stock
redis.conflistens on127.0.0.1only and turns protected mode on. Changebindand set a password. - The official image ignores
REDIS_PASSWORDandREDIS_ARGS. Pass--requirepasson the command line or use a config or ACL file. -
redis-cli pingexits 0 onNOAUTH, so a plain ping healthcheck stays healthy. SetREDISCLI_AUTHand check forPONG. -
MISCONFandappendonlydir: Permission deniedmean the Redis user (uid 999) can't write/data. Fix the ownership instead of turning the check off.
Fix Connection refused from another container
Start with the map. Find the message you see in the left column:
The lab started with the smallest possible service, no config file and no published port:
services: redis: image: redis:8.10.3 volumes: - redis-data:/data volumes: redis-data: Don't connect to localhost from the app container
A one-off redis:8.10.3 container on the same Compose network played the app:
$ redis-cli -h localhost PING Could not connect to Redis at localhost:6379: Connection refused $ redis-cli -h 127.0.0.1 -p 6379 PING Could not connect to Redis at 127.0.0.1:6379: Connection refused $ redis-cli -h redis PING PONG Each container has its own loopback interface, so localhost inside the app container is the app container. Redis listens in its own container, which Compose names after the service. Set your app's Redis host to redis (or whatever you called the service), for example redis://redis:6379/0. The container name redislab-redis-1 also answered. The MySQL guide shows the same mistake with ERROR 2002 and 2003.
From the Docker host itself, the port was closed too. docker compose ps listed 6379/tcp with no host mapping, and a TCP connect to 127.0.0.1:6379 on the host was refused. Add ports: ["127.0.0.1:6379:6379"] if a tool on the host needs Redis. Keep the 127.0.0.1 part. Other containers on the network don't need ports at all.
Check bind in a mounted redis.conf
The image docs show how to start Redis with your own redis.conf. If you start from the upstream file, note that the 8.10.3 version from the redis/redis repository contains bind 127.0.0.1 -::1 and protected-mode yes. Mounted as-is, Redis answers inside its own container and refuses everyone else:
CONFIG GET bind inside the container returned 127.0.0.1 -::1. A published port didn't help either: from the host, redis-cli got Error: Connection reset by peer. This is the accepted answer on the 306,329-view question above: the server only listens on loopback. Change the line to bind * -::*, which the same file describes as "like the default, all available interfaces". That leads straight to the next error.
Fix DENIED Redis is running in protected mode
Why the plain image has no protected mode
Without a config file, the image turns protected mode off. In the lab, CONFIG GET protected-mode returned no, bind was * -::* and requirepass was empty. Redis logged this on startup:
WARNING: Redis does not require authentication and is not protected by network restrictions. Redis will accept connections from any IP address on any network interface. The Docker Official Image docs explain the choice: "For the ease of accessing Redis from other containers via Docker networking, the "Protected mode" is turned off by default. This means that if you expose the port outside of your host (e.g., via -p on docker run), it will be open without a password to anyone."
Set a password instead of turning protected mode off
With a mounted redis.conf you get the upstream default, protected-mode yes. After the bind * -::* change and no password, every client from another container got the long DENIED reply:
The message offers four ways out. Three of them switch protected mode off. Option 4, a password for the default user, is the one to pick. Adding requirepass Lab-Pass-4821 to redis.conf and restarting turned DENIED into NOAUTH Authentication required., and the same client with the password got PONG. The Redis security docs state the design plainly: "Redis is designed to be accessed by trusted clients inside trusted environments." A password plus a private Compose network keeps it that way.
Fix NOAUTH and a password that never applied
Pass the password with --requirepass
The first lab file had REDIS_PASSWORD: "ChangeMe123" in environment. Redis started without a password anyway: CONFIG GET requirepass came back empty, and a client from another container ran PING without any auth. The entrypoint script in redis:8.10.3 never reads REDIS_PASSWORD, and it contains no REDIS_ARGS either. A test with REDIS_ARGS: "--requirepass Lab-Pass-4821" also left Redis open, and SET worked without a password. A Stack Overflow answer notes that REDIS_ARGS works with the redis/redis-stack images. The official redis image doesn't support it.
Instead, put the password in .env and let Compose interpolate it into the command:
services: redis: image: redis:8.10.3 command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:?set REDIS_PASSWORD in .env}"] With REDIS_PASSWORD=Lab-Pass-4821 in .env, this produced the errors your app shows when its password is missing or wrong:
NOAUTH Authentication required. means the client sent no password. WRONGPASS invalid username-password pair or user is disabled. means it sent the wrong one. With -a, redis-cli also prints a warning that a password on the command line may not be safe. Set REDISCLI_AUTH instead, or add --no-auth-warning. Without .env, the :? form stops Compose with required variable REDIS_PASSWORD is missing a value, so Redis never starts open by accident.
Two details from the lab. docker inspect shows the password in the container's Args. And the shell form from a 41-vote answer also worked, with redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}" after /bin/sh -c and the password in environment. The $$ stops Compose from replacing the variable itself. That keeps the value out of Args, but it still sits in the container's environment.
The healthcheck has the same blind spot, as the bottom of the screenshot above shows. A healthcheck of ["CMD", "redis-cli", "ping"] against a password-protected Redis stayed healthy. Its last probe printed NOAUTH Authentication required. and exited 0. So depends_on: condition: service_healthy lets your app start against a Redis it can't log in to.
This check reports the truth:
environment: REDISCLI_AUTH: ${REDIS_PASSWORD} healthcheck: test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"] With the right password the service was healthy. With a wrong REDISCLI_AUTH it turned unhealthy, and the probe log showed the WRONGPASS error.
Use an ACL user when your app wants a username
Some apps ask for a Redis username and password. Define the user in an ACL file:
user default off user app on >App-Pass-7730 ~app:* +@all -@dangerous Mount it read-only and start Redis with command: ["redis-server", "--aclfile", "/usr/local/etc/redis/users.acl"]. In the lab, redis-cli --user app --pass App-Pass-7730 PING returned PONG, and a URL like redis://app:App-Pass-7730@redis:6379 worked too. A password without the username failed with WRONGPASS, because the default user is off. The ~app:* key pattern did its job: SET other 1 returned NOPERM No permissions to access a key, and FLUSHALL was refused. Putting the same rules on the command line went wrong in the lab. Written as one list item after --user, Redis exited with Spaces not allowed in ACL usernames. The file avoids that.
Fix MISCONF and append-only Permission denied
Why saves to /data fail
The Redis server runs as uid 999 (redis) in this image. When the container starts as root, the entrypoint fixes the ownership of /data itself. The image docs add a limit: "This adjustment is only performed in basic, default scenarios to avoid interfering with custom or user-specific configurations."
The lab hit that limit with a bind mount, ./data:/data, owned by root and holding a .gitkeep file. The entrypoint printed Notice: Unknown file './.gitkeep' found in data dir. Permissions will not be modified. and left the directory alone. Redis started, and reads and writes worked until the first snapshot:
The default save rule was 3600 1 300 100 60 10000. After a failed BGSAVE, the log said Failed opening the temp RDB file temp-51.rdb (in server root dir /data) for saving: Permission denied, INFO persistence showed rdb_last_bgsave_status:err, and the next SET returned MISCONF. Reads still worked, as GET a returned 1.
With --appendonly yes the same mount fails at once. The container exited with code 1 after Can't open or create append-only dir appendonlydir: Permission denied. A user: "1000:1000" line on a fresh named volume, which the image creates owned by 999, failed with the same message.
Every start in the lab logged WARNING Memory overcommit must be enabled!, because the host had vm.overcommit_memory set to 0. The warning says it can make a background save fail under low memory, and it names the fix: "To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect." This is a host setting. docker run --sysctl vm.overcommit_memory=1 failed with sysctl 'vm.overcommit_memory=1' is not allowed, and the container read the host value of 0. Set it on the Docker host. A permission error, not this warning, caused every MISCONF in this lab.
Fix ownership, don't switch off the check
The 533-vote answer on the MISCONF question runs config set stop-writes-on-bgsave-error no and adds that you should check why the save failed. The lab shows why that matters. After that command, SET worked again, but the next BGSAVE still ended with rdb_last_bgsave_status:err. Nothing reached the disk.
Fix the directory instead. Any of these worked in the lab:
- Change the owner to the Redis user with
sudo chown -R 999:999 ./dataand restart. Writes worked,BGSAVEreturnedrdb_last_bgsave_status:okanddump.rdbappeared with owner 999. - Run the command from the image docs,
docker run --rm -v /your/host/path:/data redis:8.10.3 chown -R redis:redis /data. It set the same root-owned folder to 999:999. - Remove the unknown files, so the entrypoint fixes the folder on its own. With
.gitkeepgone it changed the owner to 999 and createdappendonlydir. - If you run Redis with
user: "1000:1000", make the volume belong to that user, for exampledocker run --rm -v <volume>:/data alpine:3.22 chown 1000:1000 /data. After that the AOF service started andaof_last_write_status:ok.
The Grafana and Prometheus guide walks through the same uid mismatch with two other images.
A Redis Compose file that avoids these errors
compose.yaml and .env
This file ran verbatim in the lab:
services: redis: image: redis:8.10.3 restart: unless-stopped command: - redis-server - --requirepass - ${REDIS_PASSWORD:?set REDIS_PASSWORD in .env} - --appendonly - "yes" environment: REDISCLI_AUTH: ${REDIS_PASSWORD} ports: - "127.0.0.1:6379:6379" volumes: - redis-data:/data healthcheck: test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"] interval: 10s timeout: 3s retries: 5 start_period: 5s app: image: redis:8.10.3 depends_on: redis: condition: service_healthy environment: REDISCLI_AUTH: ${REDIS_PASSWORD} command: ["redis-cli", "-h", "redis", "INCR", "app:visits"] volumes: redis-data: REDIS_PASSWORD=f3Kq9-Lab-Only-2Vx7 Replace app with your real service and give it the host redis and the same password. The named volume belongs to the Redis user from the start, AOF is on, and the healthcheck only passes on a real PONG. Drop the ports block if nothing on the host needs Redis. If your password contains $, read the dollar sign section of the MySQL guide first, because Compose interpolates .env the same way. The Umami guide uses the same service_healthy pattern with PostgreSQL.
Check it
$ docker compose up -d Container redisfinal-redis-1 Waiting Container redisfinal-redis-1 Healthy Container redisfinal-app-1 Started $ docker compose logs --no-log-prefix app 1 $ docker compose run --rm app 2 $ docker compose exec redis redis-cli INFO persistence | grep -E 'aof_enabled|aof_last_write_status' aof_enabled:1 aof_last_write_status:ok $ docker compose restart redis $ docker compose exec redis redis-cli GET app:visits 2 From the host, redis-cli -h 127.0.0.1 PING without a password got NOAUTH Authentication required., and with REDISCLI_AUTH set it read the counter. The value survived the restart. Paperless-ngx uses a Redis-compatible broker in the same way, as the Paperless-ngx guide shows with Valkey.
FAQ
Connection errors
Why does Redis refuse connections between Docker Compose containers?
Usually the app connects to localhost or 127.0.0.1, which is the app's own container. Use the service name, such as redis. If you mounted your own redis.conf, check its bind line. The stock file has bind 127.0.0.1 -::1, so other containers get Connection refused until you change it.
How do I connect to Redis in Docker from the host machine?
Publish the port, for example ports: ["127.0.0.1:6379:6379"], and connect to 127.0.0.1:6379. Without ports, the host connection is refused. If Redis uses the stock redis.conf with bind 127.0.0.1 -::1, the published port still fails. In the lab, redis-cli on the host got Error: Connection reset by peer.
How do I fix DENIED Redis is running in protected mode in Docker?
Set a password with requirepass or define an ACL user. Protected mode only blocks remote clients when the default user has no password. The plain image starts with protected mode off, so this error usually comes from a mounted redis.conf.
Password and persistence errors
How do I set a Redis password with an environment variable in docker-compose?
The official image doesn't read REDIS_PASSWORD. Put the value in .env and pass it in command, as in ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]. Check with CONFIG GET requirepass or a PING without a password, which should return NOAUTH.
How do I use a Redis username with a password in docker-compose?
Create an ACL file with user default off and a line such as user app on >password ~app:* +@all, mount it, and start Redis with --aclfile. Clients then log in with --user and --pass, or a URL like redis://app:password@redis:6379.
How do I fix MISCONF Redis is configured to save RDB snapshots in Docker?
Read the Redis log for the reason. In Docker it is often Permission denied on /data. Change the data directory's owner to uid 999, or to the user you set with user:, then restart. Setting stop-writes-on-bgsave-error no hides the error but doesn't save anything.







