Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RedisContainer

A single-node Redis container, ready-checked with a plain TCP read-probe (Wait::for_listening_port) — Redis speaks first on connect, so the bare listening-port wait is sufficient here (contrast MemcachedContainer, which needs a protocol-level probe).

Default image: floats to redis:latest — this module previously pinned redis:8.6-alpine; Docker Hub publishes redis:latest as a Debian-based image rather than Alpine, functionally equivalent for this module’s own use, just a larger pull. Guest port: 6379 Expected repository: redis

MethodOnEffect
RedisContainer::new()builderFloating default image (redis:latest).
RedisContainer::with_image(image)builderCaller-chosen image, kept verbatim.
.start()builder → Result<RedisGuard>Checks the image’s repository, then boots the container.
.uri()guardredis://host:port connection URI.
.stop()guardStops and removes the container, releases its port.

RedisGuard derefs to ContainerGuard, so exec(), logs(), get_mapped_port(), etc. are all available directly on it too.

Compatibility checking

with_image takes impl Into<ImageName> and keeps the image verbatim. start() then checks that image’s repository (registry host, tag, and digest stripped) against redis before any backend is resolved or any sandbox is created, which keeps the constructors infallible like every other module’s:

use rightsize::ImageName;
use rightsize_modules::RedisContainer;

// Checked on start, common case.
let guard = RedisContainer::with_image("redis:8").start().await?;

// A verified drop-in replacement from another registry — the escape hatch.
let guard = RedisContainer::with_image(
    ImageName::parse("mycorp/redis-hardened:8").as_compatible_substitute_for("redis"),
)
.start()
.await?;

A mismatch returns RightsizeError::IncompatibleImage — naming the supplied repository, the expected one, and the override above — rather than letting an unrelated image run all the way to a wait-strategy timeout. new() goes through this same check against its own floating reference, so it can never fail in practice.

Complete example

use rightsize_modules::RedisContainer;

#[tokio::test]
async fn cache_roundtrip() -> rightsize::Result<()> {
    let redis = RedisContainer::new().start().await?;

    let client = redis::Client::open(redis.uri()).unwrap();
    let mut con = client.get_connection().unwrap();
    redis::cmd("SET").arg("k").arg("v").execute(&mut con);
    let v: String = redis::cmd("GET").arg("k").query(&mut con).unwrap();
    assert_eq!(v, "v");

    redis.stop().await?;
    Ok(())
}

(This crate’s own integration suite proves the same connectivity with a raw TCP PING/PONG round-trip rather than pulling in the redis crate as a dev-dependency — see crates/rightsize-modules/tests/datastore_modules_it.rs.)

Backend notes

No memory-limit override and no known quirks on either backend — Redis’s default footprint is well under microsandbox’s ~450 MB default microVM RAM. Nothing else to flag here; see Backends for the general backend-difference list if you hit something unexpected.