Containerize the Storage service adapter#
Goal: Package the local filesystem service in a Docker image so you can run it in a container and later deploy it to MicroK8s with Helm.
With the storage-api package built and the service validated locally, create a Dockerfile to containerize the local filesystem service and extend your developer deployment.
┌──────────────────────────────────────────────────────┐
│ Docker Container │
│ │
│ local_filesystem_service /data/storage/ │
│ ┌────────────────────┐ ┌──────────────┐ │
│ │ REST API :8011 │──writes──>│ host volume │ │
│ │ gRPC API :50051 │ │ (persisted) │ │
│ └────────────────────┘ └──────────────┘ │
│ │
└──────────────────────────────────────────────────────┘
▲ curl / Kit / Custom client
│ port 8011 (REST) port 50051 (gRPC)
Build the wheels package#
Build the local filesystem service as a wheel to simplify the Dockerfile. Run from the filesystem_example directory.
# change to the directory to the filesystem example if you aren't already there
cd ./storage-api-1.0.0-beta.2/filesystem_example
# build the wheel package
./.poetry_venv/bin/poetry build
The wheel is created in dist/. Create a Dockerfile in the filesystem_example directory.
touch ./Dockerfile
Dockerfile#
The example Dockerfile sets up a container environment: a lightweight Python image, your service code and protocol definitions, Python dependencies, compiled gRPC protobufs, and a main script to start the service. You can then run the same image anywhere Docker is available. The default command in this guide starts the service with the explicit filesystem backend.
FROM python:3.10-slim
WORKDIR /app
COPY ./dist /dist
RUN pip install /dist/omniverse_filesystem_storage_service-*-py3-none-any.whl
ENTRYPOINT ["local-filesystem-service"]
CMD ["filesystem"]
Build the container#
docker build -f ./Dockerfile -t storageapi_localfilesystem_service:local .
Validate the container#
Create a host directory for storage data (e.g. ~/storage-data) and mount it into the container. Files written by the service will appear there on the host for debugging.
# create a directory for the storage data
mkdir -p ~/storage-data
# validate the container was built and is available in the local registry
docker images | grep storageapi_localfilesystem_service
# run the container with ports exposed, mount a host storage directory, and set a custom storage directory inside the container
docker run -d -p 8011:8011 -p 50051:50051 \
-v ~/storage-data:/data/storage \
-e FILESERVICE_STATIC_DIR=/data/storage \
-e FILESERVICE_SERVER_BASE_URI=file-storage://fileservice \
--name localfilesystem-test \
-t storageapi_localfilesystem_service:local
Note
If you are using an older image built from a Dockerfile with CMD [], append filesystem explicitly to the docker run command:
docker run -d -p 8011:8011 -p 50051:50051 \
-v ~/storage-data:/data/storage \
-e FILESERVICE_STATIC_DIR=/data/storage \
-e FILESERVICE_SERVER_BASE_URI=file-storage://fileservice \
--name localfilesystem-test \
-t storageapi_localfilesystem_service:local \
filesystem
Here’s what each argument in the docker run command above does:
-d: Runs the container in the background (detached).-p 8011:8011: Maps the container’s REST/HTTP port 8011 to port 8011 on your host, making the REST API accessible.-p 50051:50051: Maps the container’s gRPC port 50051 to port 50051 on your host, making the gRPC API accessible.-v ~/storage-data:/data/storage: Mounts the{hostpath}:{containerpath}directory from your host into the container at the same path. This allows files written by the storage service to persist on your host and makes them available after container shutdown.-e FILESERVICE_STATIC_DIR=/data/storage: Sets the environment variable inside the container so the service stores files in /data/storage.-e FILESERVICE_SERVER_BASE_URI=file-storage://fileservice: Sets the URI prefix returned and expected by the service for file-address endpoints. If you change it, use that same URI in your request paths.--name localfilesystem-test: Assigns the name “localfilesystem-test” to the container for easier management and reference.-t storageapi_localfilesystem_service:local: Specifies the image to use for the container.
Check that the container is running:
docker ps | grep localfilesystem-test
You should see output showing the container is running with both ports exposed.
Test the containerized service#
With the container running, test it the same way as in the get-started section:
# Test REST API - check available services
curl http://localhost:8011/v1beta/capabilities/services
# You should also be able to read the written data from the previous testing
curl http://localhost:8011/v1beta/fileobject/by-address/file-storage%3A%2F%2Ffileservice%2Ftest.txt
You should see the same responses as when testing the local Python service.
Viewing container logs#
To see the service logs from the running container:
docker logs localfilesystem-test
You should see output similar to this:
2025-11-26 20:55:55,654 - INFO - gRPC Server launched on port 50051
2025-11-26 20:55:55,654 - INFO - Starting static server...
2025-11-26 20:55:55,668 - INFO - Started server process [1]
2025-11-26 20:55:55,668 - INFO - Waiting for application startup.
2025-11-26 20:55:55,668 - INFO - Application startup complete.
2025-11-26 20:55:55,668 - INFO - Uvicorn running on http://0.0.0.0:8011 (Press CTRL+C to quit)
Clean up the test container#
When you’re done testing, stop and remove the container:
docker stop localfilesystem-test
Next Steps#
Next: Deploy the storage service to your MicroK8s cluster using the Helm chart.