Docker Deployment
S4 provides Docker images for easy deployment. The project includes a Dockerfile for the server and docker-compose-single-node.yml, which runs the server together with the web admin console.
Single Container
Build
docker build -t s4-server .
Run (Basic)
docker run -d \
--name s4-server \
-p 9000:9000 \
-v s4-data:/data \
s4-server:latest
Run with Credentials
docker run -d \
--name s4-server \
-p 9000:9000 \
-v s4-data:/data \
-e S4_ACCESS_KEY_ID=myaccesskey \
-e S4_SECRET_ACCESS_KEY=mysecretkey \
s4-server:latest
Run with IAM
docker run -d \
--name s4-server \
-p 9000:9000 \
-v s4-data:/data \
-e S4_ROOT_PASSWORD=password12345 \
-e S4_JWT_SECRET=your-256-bit-secret \
s4-server:latest
Run with TLS
docker run -d \
--name s4-server \
-p 9000:9000 \
-v s4-data:/data \
-v /path/to/certs:/certs:ro \
-e S4_TLS_CERT=/certs/cert.pem \
-e S4_TLS_KEY=/certs/key.pem \
s4-server:latest
Docker Compose (Full Stack)
docker-compose-single-node.yml builds the Community Edition server from the
repository and runs it together with the web admin console:
services:
s4core:
build:
context: .
dockerfile: Dockerfile
ports:
- "9000:9000"
environment:
- S4_BIND=0.0.0.0:9000
- S4_DATA_DIR=/data
- S4_ROOT_USERNAME=${S4_ROOT_USERNAME:-root}
- S4_ROOT_PASSWORD=${S4_ROOT_PASSWORD:-password12345}
- S4_ACCESS_KEY_ID=${S4_ACCESS_KEY_ID:-my-access-key-one}
- S4_SECRET_ACCESS_KEY=${S4_SECRET_ACCESS_KEY:-my-secret-key-one}
volumes:
- s4-data:/data
s4console:
image: s4core/s4console:latest
ports:
- "3000:3000"
environment:
# The console reaches the server by its compose service name.
- S4_BACKEND_URL=http://s4core:9000
depends_on:
s4core:
condition: service_healthy
volumes:
s4-data:
The excerpt leaves out the health check and restart policy. The root credentials
and the S3 keys are read from the shell, with the defaults above as placeholders:
set S4_ROOT_PASSWORD, S4_ACCESS_KEY_ID and S4_SECRET_ACCESS_KEY before
exposing the server.
Start
# Full stack: server + web console
docker compose -f docker-compose-single-node.yml up -d --build
# Server only
docker compose -f docker-compose-single-node.yml up -d --build s4core
Access Points
| Service | URL |
|---|---|
| S4 API | http://localhost:9000 |
| Web Console | http://localhost:3000 (log in as root / S4_ROOT_PASSWORD) |
The console needs IAM, which S4_ROOT_PASSWORD turns on.
Rebuild After Changes
docker compose -f docker-compose-single-node.yml up -d --build
Stop
docker compose -f docker-compose-single-node.yml down # keep the data volume
docker compose -f docker-compose-single-node.yml down -v # delete it as well
View Logs
# All services
docker compose -f docker-compose-single-node.yml logs -f
# Server only
docker compose -f docker-compose-single-node.yml logs -f s4core
Volume Management
S4 stores all data in the /data directory inside the container. Always use a Docker volume or bind mount to persist data.
# Named volume (recommended)
-v s4-data:/data
# Bind mount
-v /var/lib/s4:/data
The server runs as the unprivileged user s4 (uid 1000), so a bind-mounted
directory has to be writable by that uid: sudo chown 1000:1000 /var/lib/s4.
A directory Docker creates for a missing bind source belongs to root, and the
server cannot write to it.
Warning: Without a volume, all data is lost when the container is removed.
Cluster Deployment (Docker)
For deploying a multi-node S4 cluster with Docker Compose, see Cluster Deployment.
Resource Recommendations
| Workload | CPU | RAM | Storage |
|---|---|---|---|
| Development / Testing | 1 core | 512MB | 1GB |
| Small (< 1M objects) | 2 cores | 2GB | As needed |
| Medium (1-100M objects) | 4 cores | 8GB | As needed |
| Large (> 100M objects) | 8+ cores | 16GB+ | NVMe recommended for metadata |