Running Redis with CleanStart
CleanStart provides production-ready Redis base images (cleanstart/redis) with Redis 7.0 and 7.2 versions that include security patches. These images support Sentinel mode for high availability, persistence with AOF and RDB, and Cluster mode support. They come pre-configured with TLS and authentication capabilities.
Quick Start: Single Redis Instance
Step 1: Run Redis Container
Start a Redis container with persistent storage enabled:
docker run -d \ --name redis \ -p 6379:6379 \ -v redis-data:/data \ cleanstart/redis:7.2Step 2: Connect and Test
Test basic Redis operations using redis-cli:
# Using redis-clidocker exec -it redis redis-cli ping# Response: PONG # Set a keydocker exec -it redis redis-cli SET mykey "Hello Redis" # Get the keydocker exec -it redis redis-cli GET mykey# Response: "Hello Redis"Step 3: Verify Persistence
Check that data persists across container restarts:
# Check data directorydocker exec redis ls -la /data # Restart container - data persistsdocker restart redisdocker exec -it redis redis-cli GET mykey# Response: "Hello Redis"Production Dockerfile
Create a custom Redis image with your own configuration:
FROM cleanstart/redis:7.2 # Copy custom Redis configurationCOPY redis.conf /usr/local/etc/redis/ # Create non-root user for running RedisRUN useradd -m -u 1000 redis # Health checkHEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \ CMD redis-cli ping || exit 1 # Run as non-rootUSER redis EXPOSE 6379VOLUME /data CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]Create redis.conf with production settings for persistence and memory management:
# Networkport 6379bind 0.0.0.0tcp-backlog 511timeout 0tcp-keepalive 300 # Persistencedir /datasave 900 1 # Save if 900 seconds and 1 key changesave 300 10 # Save if 300 seconds and 10 key changessave 60 10000 # Save if 60 seconds and 10000 key changesstop-writes-on-bgsave-error yesrdbcompression yesrdbchecksum yesdbfilename dump.rdb # AOF (Append Only File)appendonly yesappendfilename "appendonly.aof"appendfsync everysec # Fsync every secondno-appendfsync-on-rewrite no # Memorymaxmemory 512mbmaxmemory-policy allkeys-lru # Replicationrepl-diskless-sync norepl-diskless-sync-delay 5 # Loggingloglevel noticelogfile ""syslog-enabled noBuild and run the custom image:
docker build -t my-redis:latest .docker run -d \ --name my-redis \ -p 6379:6379 \ -v redis-data:/data \ my-redis:latestDocker Compose: Redis with Persistence
Run Redis with a UI tool for visual management:
version: '3.9' services: redis: image: cleanstart/redis:7.2 container_name: my-redis command: > redis-server --port 6379 --appendonly yes --appendfsync everysec --maxmemory 512mb --maxmemory-policy allkeys-lru ports: - "6379:6379" volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 3 start_period: 5s networks: - app-network redis-commander: image: rediscommander/redis-commander:latest container_name: redis-commander environment: - REDIS_HOSTS=local:redis:6379 ports: - "8081:8081" depends_on: - redis networks: - app-network volumes: redis-data: networks: app-network:Run: docker-compose up -d
High Availability: Redis Sentinel
Sentinel Configuration
Create sentinel.conf for high availability setup:
port 26379 # Master monitoringsentinel monitor mymaster 127.0.0.1 6379 2sentinel down-after-milliseconds mymaster 5000sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 180000 # Loggingloglevel noticelogfile ""Docker Compose: Sentinel Setup
Set up a complete Sentinel cluster with master and replicas:
version: '3.9' services: redis-master: image: cleanstart/redis:7.2 container_name: redis-master command: redis-server --port 6379 --appendonly yes ports: - "6379:6379" volumes: - redis-master-data:/data networks: - redis-network redis-replica-1: image: cleanstart/redis:7.2 container_name: redis-replica-1 command: redis-server --port 6380 --slaveof redis-master 6379 --appendonly yes ports: - "6380:6380" depends_on: - redis-master volumes: - redis-replica-1-data:/data networks: - redis-network redis-replica-2: image: cleanstart/redis:7.2 container_name: redis-replica-2 command: redis-server --port 6381 --slaveof redis-master 6379 --appendonly yes ports: - "6381:6381" depends_on: - redis-master volumes: - redis-replica-2-data:/data networks: - redis-network redis-sentinel-1: image: cleanstart/redis:7.2 container_name: redis-sentinel-1 command: redis-sentinel /etc/redis/sentinel.conf ports: - "26379:26379" volumes: - ./sentinel.conf:/etc/redis/sentinel.conf - sentinel-1-data:/data depends_on: - redis-master - redis-replica-1 - redis-replica-2 networks: - redis-network redis-sentinel-2: image: cleanstart/redis:7.2 container_name: redis-sentinel-2 command: redis-sentinel /etc/redis/sentinel.conf ports: - "26380:26379" volumes: - ./sentinel.conf:/etc/redis/sentinel.conf - sentinel-2-data:/data depends_on: - redis-master - redis-replica-1 - redis-replica-2 networks: - redis-network redis-sentinel-3: image: cleanstart/redis:7.2 container_name: redis-sentinel-3 command: redis-sentinel /etc/redis/sentinel.conf ports: - "26381:26379" volumes: - ./sentinel.conf:/etc/redis/sentinel.conf - sentinel-3-data:/data depends_on: - redis-master - redis-replica-1 - redis-replica-2 networks: - redis-network volumes: redis-master-data: redis-replica-1-data: redis-replica-2-data: sentinel-1-data: sentinel-2-data: sentinel-3-data: networks: redis-network: driver: bridgeDeploy and test the Sentinel setup:
docker-compose up -d # Check master-replica replicationdocker exec redis-master redis-cli INFO replication # Monitor Sentineldocker exec redis-sentinel-1 redis-cli -p 26379 SENTINEL mastersPassword Protection
Enable Authentication
Run Redis with a password requirement:
docker run -d \ --name redis-secure \ cleanstart/redis:7.2 \ redis-server \ --requirepass mysecurepassword \ --appendonly yesClient Connection
Connect with authentication:
# Connect with passworddocker exec -it redis-secure redis-cli -a mysecurepassword ping # Or using AUTH commanddocker exec -it redis-secure redis-cli> AUTH mysecurepassword> PINGKubernetes Deployment
Create redis-statefulset.yaml for production Kubernetes:
apiVersion: apps/v1kind: StatefulSetmetadata: name: redisspec: serviceName: redis replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: cleanstart/redis:7.2 ports: - containerPort: 6379 name: redis command: - redis-server - "--appendonly" - "yes" - "--maxmemory" - "512mb" - "--maxmemory-policy" - "allkeys-lru" volumeMounts: - name: data mountPath: /data livenessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 5 periodSeconds: 5 resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m" volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi ---apiVersion: v1kind: Servicemetadata: name: redisspec: ports: - port: 6379 targetPort: 6379 name: redis selector: app: redisDeploy: kubectl apply -f redis-statefulset.yaml
Performance Tuning
Memory Management
Set memory limits and eviction policies:
docker run -d \ --name redis-tuned \ cleanstart/redis:7.2 \ redis-server \ --maxmemory 1gb \ --maxmemory-policy allkeys-lru \ --appendonly yesNetwork Optimization
Optimize network settings:
redis-server \ --tcp-backlog 511 \ --tcp-keepalive 300 \ --timeout 0Persistence Options
Choose persistence strategy based on your needs:
# RDB snapshots only (faster, less safe)redis-server --save "900 1" --appendonly no # AOF only (slower, safer)redis-server --appendonly yes --appendfsync everysec # Both RDB and AOF (balanced)redis-server --save "900 1" --appendonly yesMonitoring and Debugging
Server Info
Get Redis server statistics:
docker exec redis redis-cli INFO serverdocker exec redis redis-cli INFO memorydocker exec redis redis-cli INFO statsMonitor Commands in Real-Time
Watch all commands as they happen:
docker exec -it redis redis-cli MONITORCheck Memory Usage
Monitor how much memory Redis is using:
docker exec redis redis-cli INFO memory | grep used_memory_humanList All Keys
View all keys in the database:
docker exec redis redis-cli KEYS "*"Troubleshooting
Connection refused: Check port mapping and firewall rules Out of memory: Increase container memory or adjust maxmemory policy Replication lag: Monitor network and increase network buffers Slow persistence: Use AOF fsync everysec instead of always
Image Options
Image | Use Case |
|---|---|
| Stable LTS (recommended) |
| Legacy support |
CleanStart Production Hardening
Read-Only Root Filesystem
Enforce immutable infrastructure with read-only root, with writable paths for Redis data:
apiVersion: v1kind: Podmetadata: name: redisspec: containers: - name: redis image: cleanstart/redis:7.2 securityContext: readOnlyRootFilesystem: true volumeMounts: - name: data mountPath: /data - name: run mountPath: /var/run/redis - name: tmp mountPath: /tmp volumes: - name: data persistentVolumeClaim: claimName: redis-data - name: run emptyDir: {} - name: tmp emptyDir: {}Shell-Less ENTRYPOINT
Remove shell for attack surface reduction. Update your Dockerfile:
FROM cleanstart/redis:7.2 # Copy custom Redis configurationCOPY redis.conf /usr/local/etc/redis/redis.conf # Declarative Image Builder: Use cleanimg-init as PID 1ENTRYPOINT ["/cleanimg-init", "--"]CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]cleanimg-customize: Redis Configuration
Inject production security and persistence settings:
FROM cleanstart/redis:7.2 # Create custom configuration with security hardeningRUN echo 'requirepass ""' >> /usr/local/etc/redis/redis.conf && \ echo 'appendonly yes' >> /usr/local/etc/redis/redis.conf && \ echo 'appendfsync everysec' >> /usr/local/etc/redis/redis.conf && \ echo 'maxmemory 512mb' >> /usr/local/etc/redis/redis.conf && \ echo 'maxmemory-policy allkeys-lru' >> /usr/local/etc/redis/redis.conf && \ echo 'bind 127.0.0.1' >> /usr/local/etc/redis/redis.conf ENTRYPOINT ["/cleanimg-init", "--"]CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]Security Context
Complete Kubernetes securityContext for hardened Redis containers:
apiVersion: apps/v1kind: StatefulSetmetadata: name: redisspec: template: spec: securityContext: fsGroup: 999 seccompProfile: type: RuntimeDefault containers: - name: redis image: cleanstart/redis:7.2 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 999 runAsGroup: 999 capabilities: drop: - ALL add: - NET_BIND_SERVICE resources: requests: cpu: 100m memory: 256Mi limits: cpu: 500m memory: 512MiNext Steps
For next steps in your Redis journey, explore advanced Redis configuration options, learn about Redis Cluster Deployment in the clustering guide, and review Redis Monitoring and Alerting for operational insights.
