Skip to content

trino-rustfs

What it demonstrates

puddle catalog backed by rustfs (a local S3-compatible object store) with Trino wired up as a query engine. No auth. The smallest end-to-end Iceberg + S3 + Trino loop.

Run it

cd examples/compose/trino-rustfs
docker compose up

docker-compose.yml

Source on GitHub.

docker-compose.yml
# Self-contained docker-compose for running puddle with rustfs (an
# S3-compatible object store) as the warehouse and Trino as a query
# engine. No auth — anyone can do anything.
#
# Run:
#   docker compose up
# Trino UI:    http://localhost:8080
# Catalog REST: http://localhost:8089/api/catalog
#
# In Trino:
#   CREATE SCHEMA iceberg.demo;
#   CREATE TABLE iceberg.demo.t (id bigint, name varchar);
#   INSERT INTO iceberg.demo.t VALUES (1, 'hello');
#   SELECT * FROM iceberg.demo.t;

configs:
  puddle-config:
    content: |
      logging:
        level: info
        format: text

      metastore:
        type: sqlite
        sqlite:
          path: /var/lib/puddle/puddle.db

      warehouses:
        default:
          location: s3://puddle/warehouse
          s3:
            region: us-east-1
            endpoint: http://rustfs:9000
            path-style-access: true
            access-key-id: puddle-example-key
            secret-access-key: puddle-example-secret

  trino-iceberg:
    content: |
      connector.name=iceberg
      iceberg.catalog.type=rest
      iceberg.rest-catalog.uri=http://puddle:8089/api/catalog
      iceberg.rest-catalog.warehouse=default

      # S3 client config — Trino's native S3 file system. The catalog
      # itself never serves data; Trino reaches rustfs directly using
      # these credentials.
      fs.native-s3.enabled=true
      s3.endpoint=http://rustfs:9000
      s3.region=us-east-1
      s3.path-style-access=true
      s3.aws-access-key=puddle-example-key
      s3.aws-secret-key=puddle-example-secret

services:
  puddle:
    image: ghcr.io/ragnard/puddle:latest
    ports: ["8089:8089"]
    volumes:
      - puddle-data:/var/lib/puddle
    configs:
      - source: puddle-config
        target: /etc/puddle/puddle.yaml
    command: ["/puddle", "-c", "/etc/puddle/puddle.yaml"]
    depends_on:
      rustfs-init:
        condition: service_completed_successfully
    restart: unless-stopped

  rustfs:
    image: rustfs/rustfs:latest
    environment:
      RUSTFS_ADDRESS: 0.0.0.0:9000
      RUSTFS_CONSOLE_ADDRESS: 0.0.0.0:9001
      RUSTFS_CONSOLE_ENABLE: "true"
      RUSTFS_VOLUMES: /data/rustfs0
      RUSTFS_ACCESS_KEY: puddle-example-key
      RUSTFS_SECRET_KEY: puddle-example-secret
    ports: ["9000:9000", "9001:9001"]
    volumes:
      - rustfs-data:/data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:9000/health"]
      interval: 5s
      timeout: 3s
      retries: 20
      start_period: 5s
    restart: unless-stopped

  rustfs-init:
    image: amazon/aws-cli:latest
    environment:
      AWS_ACCESS_KEY_ID: puddle-example-key
      AWS_SECRET_ACCESS_KEY: puddle-example-secret
      AWS_DEFAULT_REGION: us-east-1
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        aws --endpoint-url http://rustfs:9000 s3api create-bucket \
          --bucket puddle 2>&1 | grep -v BucketAlreadyOwnedByYou || true
    depends_on:
      rustfs:
        condition: service_healthy
    restart: "no"

  trino:
    image: trinodb/trino:latest
    ports: ["8080:8080"]
    configs:
      - source: trino-iceberg
        target: /etc/trino/catalog/iceberg.properties
    depends_on:
      puddle:
        condition: service_started
    restart: unless-stopped

volumes:
  puddle-data:
  rustfs-data: