How to Fix Docker Volume Permissions for Redis and Redis Insight with an Init Container
This guide explains why Redis and Redis Insight containers fail to start due to mismatched host directory ownership, and provides a step‑by‑step solution using a dedicated permissions‑init container, Docker Compose configuration, and a Bash script to correct the permissions safely and idempotently.
Problem Background and Cause
Redis 8.x introduced stricter security checks that validate data‑directory permissions, while the Redis Insight image runs as user 1000:1000. The host‑mounted directories are owned by root, so both containers cannot access their data directories.
uid=1000(node) gid=1000(node) groups=1000(node)
uid=999(redis) gid=999(redis) groups=999(redis)Debug tip: Use docker exec <em>container_name</em> id to discover the UID/GID a container runs as.
The Docker volume mount mechanism preserves the host directory's ownership inside the container. When the host owner does not match the container's runtime user, the service fails with permission errors.
Solution Architecture
A dedicated permissions‑init container is introduced to adjust host directory ownership before the main services start.
Docker Compose Implementation
version: '3.3'
services:
# Permission‑initialisation container
permissions-init:
image: registry.cn-chengdu.aliyuncs.com/jxd134/redis:8.4.0-bookworm
container_name: permissions-init
entrypoint: ["/bin/bash", "/scripts/fix-permissions.sh"]
volumes:
- ./data:/redis-data
- ./redisinsight:/redisinsight-data
- ./conf:/redis-conf
- ./fix-permissions.sh:/scripts/fix-permissions.sh:ro
restart: "no"
user: root
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
redis8:
image: registry.cn-chengdu.aliyuncs.com/jxd134/redis:8.4.0-bookworm
container_name: redis8
network_mode: host
restart: unless-stopped
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./data:/data
- ./conf/redis.conf:/usr/local/etc/redis/redis.conf:ro
- ./conf/users.acl:/usr/local/etc/redis/users.acl
# Note: official docs say the container runs as redis, but we observed root; we therefore set the user explicitly
user: "redis:redis"
depends_on:
- permissions-init
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
redis-insight:
image: registry.cn-chengdu.aliyuncs.com/jxd134/redisinsight:3.0.2-amd64
container_name: redis-insight
network_mode: host
restart: unless-stopped
volumes:
- ./redisinsight:/data
environment:
- REDISINSIGHT_HOST=0.0.0.0
- REDISINSIGHT_PORT=5540
depends_on:
- permissions-init
user: "1000:1000"
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"Permission Fix Script
#!/bin/bash
set -e
echo "Starting permission fix script..."
# Define directories and desired owners
declare -A dirs=(
["/redis-data"]="redis:redis"
["/redisinsight-data"]="1000:1000"
)
# Process each directory
for dir in "${!dirs[@]}"; do
if [ -d "$dir" ]; then
if [ ! -f "$dir/.permissions_fixed" ]; then
echo "Fixing $dir permissions (owner: ${dirs[$dir]})..."
chown -R "${dirs[$dir]}" "$dir"
chmod -R 755 "$dir"
touch "$dir/.permissions_fixed"
chown "${dirs[$dir]}" "$dir/.permissions_fixed"
chmod 644 "$dir/.permissions_fixed"
echo "$dir permissions fixed successfully"
else
echo "$dir permissions already fixed, skipping..."
fi
else
echo "Warning: $dir not found"
fi
done
# Fix Redis ACL file permissions if present
if [ -f "/redis-conf/users.acl" ]; then
echo "Fixing users.acl permissions..."
chown redis:redis /redis-conf/users.acl
chmod 644 /redis-conf/users.acl
echo "users.acl permissions fixed"
fi
echo "Permission fix completed successfully"Solution Summary
The core of the approach is the permissions‑init container, which acts as a "permission coordinator" before the Redis and Redis Insight services start.
Pre‑permission coordination: Using depends_on in Docker Compose, the init container runs first with root privileges to modify host directory ownership.
Scripted permission fixing: fix-permissions.sh maps each mounted path to the required UID:GID (e.g., /redis-data → redis:redis, /redisinsight-data → 1000:1000) and applies chown and chmod accordingly.
Idempotency guarantee: The script creates a hidden .permissions_fixed flag file after fixing a directory, preventing repeated changes on subsequent deployments.
Exact ownership matching: The Redis service is configured with user: "redis:redis" and Redis Insight with user: "1000:1000", ensuring each container can read/write its data after the init step.
This centralized initialization decouples permission management from the service containers, improving security and deployment reliability.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
