S3-compatible endpoint for local dev and tests, from devcloud (Rust). Listens on MinIO's port 9000.
245
A lightweight, S3-compatible endpoint for local development and deterministic tests. It is the S3 service of devcloud, packaged as a standalone Rust binary — no orchestrator, dashboard, or other services.
It listens on MinIO's API port 9000, so it can stand in for MinIO in most local setups. It is not intended for production use or full AWS parity.
linux/amd64, linux/arm64latest, 0.3.0, 0.2.0, 0.1.0 (see Changelog)services/s3)docker run --rm -p 9000:9000 -v devcloud-s3-data:/data simota/devcloud-s3
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1
aws --endpoint-url http://localhost:9000 s3 mb s3://my-bucket
aws --endpoint-url http://localhost:9000 s3 cp ./file.txt s3://my-bucket/
aws --endpoint-url http://localhost:9000 s3 ls s3://my-bucket
In the default relaxed auth mode any credentials are accepted. Use path-style addressing in SDKs (for example forcePathStyle: true / s3={'addressing_style': 'path'}).
services:
s3:
image: simota/devcloud-s3:0.3.0
ports:
- "9000:9000"
environment:
DEVCLOUD_S3_BUCKETS: uploads,backups
volumes:
- s3-data:/data
volumes:
s3-data:
| Variable | Default | Description |
|---|---|---|
DEVCLOUD_S3_ADDR | 0.0.0.0:9000 | Listen address (host:port). |
DEVCLOUD_S3_STORAGE | /data | Storage root for buckets and objects. |
DEVCLOUD_S3_AUTH_MODE | relaxed | relaxed accepts any request; strict verifies AWS SigV4 signatures. |
DEVCLOUD_S3_ACCESS_KEY_ID | dev | Access key accepted in strict mode. |
DEVCLOUD_S3_SECRET_ACCESS_KEY | — | Secret key used to verify signatures in strict mode. |
DEVCLOUD_S3_REGION | us-east-1 | Region expected in SigV4 signatures in strict mode. |
DEVCLOUD_S3_BUCKETS | — | Comma-separated buckets to create at startup (since 0.3.0). Blank entries are skipped and existing buckets are kept. An invalid bucket name stops startup with exit code 2. |
Create buckets at startup:
docker run --rm -p 9000:9000 -e DEVCLOUD_S3_BUCKETS=uploads,backups simota/devcloud-s3
Strict mode example:
docker run --rm -p 9000:9000 \
-e DEVCLOUD_S3_AUTH_MODE=strict \
-e DEVCLOUD_S3_ACCESS_KEY_ID=mykey \
-e DEVCLOUD_S3_SECRET_ACCESS_KEY=mysecret \
simota/devcloud-s3
The container runs as a non-root user (UID 10001). Data persists in the /data volume; mount a named volume or a host directory writable by that UID. It stops cleanly on SIGTERM (docker stop).
| Feature | Status |
|---|---|
| Buckets: create, head, list, delete, location | Yes |
| Objects: put, get, head, delete, copy, range GET, metadata | Yes |
ListObjects / ListObjectsV2 (prefix, delimiter, pagination, encoding-type=url) | Yes |
| Multipart upload (create, upload part, list, complete, abort) | Yes |
| Content-MD5 validation | Yes |
Conditional requests: If-None-Match on GET/HEAD (304); If-None-Match: * on PutObject, CopyObject, CompleteMultipartUpload (412); x-amz-copy-source-if-none-match | Yes (since 0.2.0) |
| SigV4 header auth and presigned URLs | Yes — signatures are verified in strict mode |
| Path-style addressing | Yes (default) |
Virtual-host style ({bucket}.localhost) | Partial |
| Versioning, delete markers, ListObjectVersions | Partial |
| Bucket policy / ACL metadata | Partial — stored, IAM not enforced |
| Lifecycle (expiration), notifications, replication, Object Lock | Partial — local behavior only |
| SSE-S3 / SSE-KMS | Partial — headers/metadata only, no real encryption or KMS |
| S3 Select | Partial — SELECT * FROM S3Object for CSV / JSON Lines |
| Inventory / analytics configuration | Partial |
9001).MINIO_ROOT_USER / MINIO_ROOT_PASSWORD are not recognized; use the DEVCLOUD_S3_* variables above./data volume between multiple containers; locking is in-process only.DEVCLOUD_S3_BUCKETS variable: comma-separated buckets are created before the listener starts. Blank entries are skipped, existing buckets are kept, and an invalid bucket name stops startup with exit code 2.If-None-Match on GET/HEAD: returns 304 Not Modified when the object's ETag matches (* or an ETag list; quoted, unquoted, or weak). It is evaluated before Range and against the requested versionId. The 304 response has no Content-Length.If-None-Match: * on PutObject, CopyObject, and CompleteMultipartUpload: returns 412 PreconditionFailed when a current object exists. Delete markers count as absent. Other values return 501.x-amz-copy-source-if-none-match against the source ETag.9000 for linux/amd64 and linux/arm64.Content type
Image
Digest
sha256:d09029731…
Size
27.8 MB
Last updated
3 days ago
docker pull simota/devcloud-s3