Installing RustFS with Docker

RustFS Docker deployment.

RustFS is a high-performance, S3-compatible open-source distributed object storage system. In single-node single-disk (SNSD) deployment mode, the backend uses zero erasure coding without additional data redundancy, suitable for local testing and small-scale scenarios. This article is based on RustFS official Linux binary packages, packaging RustFS and its runtime environment into containers through custom Dockerfile, and configuring data volumes and environment variables for one-click service startup.


Prerequisites

  1. Host Requirements
  • Docker installed (≥ 20.10) and able to pull images and run containers normally
  • Local path /mnt/rustfs/data (or custom path) for mounting object data
  • rc installed on the administration host for the verification workflow
  1. Network and Firewall
  • Ensure host ports 9000 (S3 API) and 9001 (Console) are open to external access (or consistent with custom ports)
  1. Directory Permissions
  • The RustFS container runs as non-root user rustfs with id 10001. If you run docker with -v to mount a host directory into the container, make sure the owner of the host directory is 10001, otherwise you will encounter permission denied errors. Run chown -R 10001:10001 /path/to/host_directory to grant the necessary permissions.

Pull the RustFS Official Image

Pull the official image (Alpine-based) from Docker Hub:

docker pull rustfs/rustfs

Run RustFS Container

RustFS SNSD Docker running method, combining the above image and configuration, execute:

 docker run -d \
  --name rustfs_local \
  -p 9000:9000 \
  -p 9001:9001 \
  -v /mnt/rustfs/data:/data \
  rustfs/rustfs:latest \
  /data

Parameter descriptions:

  • -p 9000:9000: Map host port 9000 to container
  • -v /mnt/rustfs/data:/data: Mount data volume
  • --name rustfs_local: Custom container name
  • -d: Run in background

Complete Configuration Example

Configuration can be passed as environment variables (recommended) or as command-line flags — pick one style; when both are present, command-line flags win. The volume path (/data) always comes last.

# Use a unique access key and a strong, random secret (e.g. openssl rand -base64 24)
docker run -d \
  --name rustfs \
  -p 9000:9000 \
  -p 9001:9001 \
  -v /mnt/rustfs/data:/data \
  -e RUSTFS_ACCESS_KEY="<your-access-key>" \
  -e RUSTFS_SECRET_KEY="<your-secret-key>" \
  -e RUSTFS_ADDRESS=:9000 \
  -e RUSTFS_CONSOLE_ENABLE=true \
  rustfs/rustfs:latest \
  /data

Common Configuration Combinations

  1. Basic Configuration:

    docker run -d \
      -p 9000:9000 \
      -p 9001:9001 \
      -v /mnt/data:/data \
      rustfs/rustfs:latest \
      /data
  2. Enable Console:

    docker run -d \
      -p 9000:9000 \
      -p 9001:9001 \
      -v /mnt/data:/data \
      -e RUSTFS_CONSOLE_ENABLE=true \
      rustfs/rustfs:latest \
      --console-enable \
      /data
  3. Custom Authentication Keys:

    # Use a unique access key and a strong, random secret (e.g. openssl rand -base64 24)
    docker run -d \
      -p 9000:9000 \
      -p 9001:9001 \
      -v /mnt/data:/data \
      -e RUSTFS_ACCESS_KEY="<your-access-key>" \
      -e RUSTFS_SECRET_KEY="<your-secret-key>" \
      rustfs/rustfs:latest \
      --access-key "<your-access-key>" \
      --secret-key "<your-secret-key>" \
      /data

Important Notes

  1. Port mapping must correspond:

    • Service port defaults to 9000 (-p 9000:9000)
  2. Data volumes must be persistent:

    • -v /host/path:/container/path
  3. Environment variables and command line parameters can be mixed, but command line parameters have higher priority

  4. If using TLS, additional certificate path mounting is needed:

    -v /path/to/certs:/certs \
    -e RUSTFS_TLS_PATH=/certs \

Docker Compose Installation

RustFS officially provides a Docker Compose installation method. The docker-compose.yml file includes multiple services, such as grafana, prometheus, otel-collector, and jaeger, mainly for observability. If you want to deploy these services together, clone the RustFS code repository locally,

git clone https://github.com/rustfs/rustfs.git

Running the command under root directory,

docker compose --profile observability up -d

Providing the necessary permissions. An initialization container is necessary to grant the correct access rights to rustfs using the depends_on keyword. In the example below the rustfs_perms service is added to the docker-compose.yml to handle this. To ensure logs are persisted and accessible, we map the host log directory to the container's /logs path

docker-compose.yml
  services:
    # grant the necessary permissions to RUSTFS volumes path
    rustfs_perms:
      image: alpine
      user: root
      volumes:
        - /path/to/host_directory/volumes:/fix_path
      command: chown -R 10001:10001 /fix_path
    
    rustfs:
      image: rustfs/rustfs:latest
      depends_on: 
        rustfs_perms:
          condition: service_completed_successfully
      volumes:
        - /path/to_host_directory/volumes/data:/data
        - /path/to_host_directory/volumes/logs:/logs
      environment:
        - RUSTFS_OBS_LOG_DIRECTORY=/logs
    
      # ... other configurations

Started containers is as below,

CONTAINER ID   IMAGE                                             COMMAND                  CREATED         STATUS                            PORTS                                                                                                                                     NAMES
c13c23fe3d9d   rustfs/rustfs:latest                              "/entrypoint.sh rust…"   6 seconds ago   Up 5 seconds (health: starting)   0.0.0.0:9000-9001->9000-9001/tcp, :::9000-9001->9000-9001/tcp                                                                             rustfs-server
e3f4fc4a83a2   grafana/grafana:latest                            "/run.sh"                7 seconds ago   Up 5 seconds                      0.0.0.0:3000->3000/tcp, :::3000->3000/tcp                                                                                                 grafana
71ef1b8212cf   prom/prometheus:latest                            "/bin/prometheus --c…"   7 seconds ago   Up 5 seconds                      0.0.0.0:9090->9090/tcp, :::9090->9090/tcp                                                                                                 prometheus
e7db806b2d6f   jaegertracing/all-in-one:latest                   "/go/bin/all-in-one-…"   7 seconds ago   Up 5 seconds                      4317-4318/tcp, 9411/tcp, 0.0.0.0:14250->14250/tcp, :::14250->14250/tcp, 14268/tcp, 0.0.0.0:16686->16686/tcp, :::16686->16686/tcp          jaeger
1897830a2f1e   otel/opentelemetry-collector-contrib:latest       "/otelcol-contrib --…"   7 seconds ago   Up 5 seconds                      0.0.0.0:4317-4318->4317-4318/tcp, :::4317-4318->4317-4318/tcp, 0.0.0.0:8888-8889->8888-8889/tcp, :::8888-8889->8888-8889/tcp, 55679/tcp   otel-collector

If you only want to install RustFS without Grafana, Prometheus, and the other observability services, start just the rustfs service (the compose file marks the collector dependency as optional):

docker compose -f docker-compose.yml up -d rustfs

This way will only install and start rustfs-server service, namely rustfs container,

docker ps
CONTAINER ID   IMAGE                                             COMMAND                  CREATED         STATUS                           PORTS                                                           NAMES
e07121ecdd39   rustfs/rustfs:latest                              "/entrypoint.sh rust…"   2 seconds ago   Up 1 second (health: starting)   0.0.0.0:9000-9001->9000-9001/tcp, :::9000-9001->9000-9001/tcp   rustfs-server

Whether you start only the rustfs-server or together with observability services, the S3 API is served at http://localhost:9000, and the RustFS Console is at http://localhost:9001 — open it in a browser and log in with the access key and secret key you configured above (the <your-access-key> / <your-secret-key> placeholders). Generate a strong secret with, for example, openssl rand -base64 24, and never ship the placeholder values to production.

Set container credentials immediately

Set unique RUSTFS_ACCESS_KEY and RUSTFS_SECRET_KEY environment variables before exposing RustFS to a network. Do not use the well-known rustfsadmin value for either credential. For docker run, pass both values with -e. For Docker Compose, define both variables in the rustfs service environment or in the environment file used for variable substitution, then recreate the service with docker compose up -d rustfs.

Verification and Access

  1. View Container Status and Logs:
docker logs rustfs_local

Logs should show successful service startup and listening on port 9000.

  1. Test S3 API:

Use rc to verify the S3 API:

# Use a unique access key and a strong, random secret (e.g. openssl rand -base64 24)
rc alias set rustfs http://localhost:9000 <your-access-key> <your-secret-key>
rc bucket create rustfs/my-bucket
rc bucket list rustfs/

If buckets can be successfully created and listed, deployment is effective.

Multiple Nodes

Dockers default bridge networking does not support multi-node deployments. Use --network host so each container can communicate directly with other nodes.

Run the following on each node

# Use a unique access key and a strong, random secret (e.g. openssl rand -base64 24)
docker run -d \
  --name rustfs \
  --network host \
  -v /mnt/rustfs/data:/data \
  -e RUSTFS_ACCESS_KEY="<your-access-key>" \
  -e RUSTFS_SECRET_KEY="<your-secret-key>" \
  -e RUSTFS_CONSOLE_ENABLE=true \
  -e RUSTFS_VOLUMES="http://node{1...4}:9000/data/rustfs{0...3}" \
  rustfs/rustfs:latest

Add the entries to /etc/hosts on every node:

/etc/hosts
192.168.1.1 node1
192.168.1.2 node2
192.168.1.3 node3
192.168.1.4 node4

Other Recommendations

  1. Production Environment Recommendations:
  1. Storage Recommendations:
  • Use local SSD/NVMe storage
  • Avoid using network file systems (NFS)
  • Ensure storage directory exclusive access

Summary

This article explains how to deploy RustFS using Docker with best practices, starting with a single-node single-disk (SNSD) setup and then extending to a multi-node deployment option.

On this page