Containerizing the Service#

With the Service now supporting tests, we can grow more confident in our ability to:

  • Identify potential stability issues.

  • Catch potential regressions if future changes introduce unintended side-effects.

  • Support greater collaboration within members of a team, since onboarding new members does not put stability or resiliency of production Services at risk.

This not only allows us to iterate faster on enhancements moving forward, it also means we can grow more confident deploying our Service to a larger number of Users.

To this end, we can consider including our feature as a Docker container so it can easily be deployed into production environments, and scaled horizontally or vertically based on the end User’s cases. In the spirit of this series, we’ll opt for Linux-based Docker containers for convenience, but know that Windows environments could have served just as well.

Writing Docker containers#

Let’s start by including the extension implementing our service into a Dockerfile extending the official Omniverse Kit image available from NVIDIA’s NGC.

Note

If you are not already set up to use NGC, you may wish to consult our guide about Containerizing Omniverse Services to quickly get started.

Once set up, let’s simply copy our extension into a Kit container (assuming the Dockerfile is located at the root of your project):

Dockerfile#
 1# syntax=docker/dockerfile:1
 2
 3# Use the official Omniverse Kit container image available from NGC.
 4#
 5# Note that while we expect the Service we created to be stable across multiple versions of the Omniverse Kit
 6# application, it may be advisable to specify a version number nonetheless in order to ensure that our container will
 7# be built against a known good version of the application. Otherwise, it is also possible to use the `:latest` tag to
 8# rely on the most recent version available at the time of building.
 9#
10# This can additionally be beneficial if building multiple containers for various different projects, as Docker layers
11# can be cached and reused, thus limiting storage requirements.
12FROM nvcr.io/nvidia/omniverse/kit:104.0.0
13
14
15# Include labels from the "Open Container Initiative" (OCI) to document the features of the container. This is useful
16# when distributing the container, especially once the number of Services you have available start increasing as you
17# author more of them over time:
18LABEL \
19    org.opencontainers.image.base.name="nvcr.io/nvidia/omniverse/kit:104.0.0" \
20    org.opencontainers.image.title="Viewport Capture Service" \
21    org.opencontainers.image.description="Example of an Omniverse viewport capture Service"
22
23
24# Let's copy our extension in a location where we can easily collect any extensions we may wish to bundle with our
25# container:
26COPY ./exts/omni.services.example.viewport_capture.core /opt/nvidia/omniverse/services/
27
28# Launch an instance of Omniverse Kit, mapping the folder where we copied our extension before enabling it:
29ENTRYPOINT [ \
30    "/opt/nvidia/omniverse/kit-sdk-launcher/kit", \
31        "--ext-folder", "/opt/nvidia/omniverse/services/", \
32        "--enable", "omni.services.example.viewport_capture.core", \
33        "--allow-root", \
34        "--no-window", \
35]
36
37# Expose ports used by the HTTP server bundled in Omniverse Kit and used for the Services stack:
38EXPOSE 8011/tcp
39
40# Perform health-check on the container at regular interval, ignoring any false-negative results that may arise within
41# the first 10 minutes due to the application potentially not being responsive because of application launch sequence,
42# during which the warm-up and shader cache generation may cause it to miss check-ins:
43HEALTHCHECK \
44    --start-period=10m \
45    --interval=5m \
46    --timeout=30s \
47    --retries=3 \
48    CMD curl --fail http://localhost:8011/docs || exit 1

To build and execute this container, all that is required is then to execute the following from a terminal:

docker build -t capture-stage-service .
docker run -it -p 8011:8011 capture-stage-service:latest

Note

Note that for brevity, we have assumed that for the workflows demonstrated in this article series, the incoming request would feature USD stages available on Nucleus servers reachable by the instance of our Omniverse application.

For more details on the configuration options of Nucleus servers, consult the section about deploying Nucleus to production.

About container startup times#

Please note that containers do not come bundled with application or shader caches, as these are closely tied to the driver, GPU and Omniverse build that are used.

As a result, containers interfacing with the GPU will require some time to complete their initialization process during their initial launch, as the caches are generated and the application is being warmed up. In cases where the container will be repeatedly running on the same known driver/GPU hardware combination, it may be worth running the container a first time to perform a warm-up process before using a docker commit to capture the state of the container.

This will significantly reduce the startup time of the container for subsequent executions of the container on the same driver/GPU combination.

Conclusion#

And there you have it! A Docker container with our Service, ready to be deployed.

 
« Previous section: Providing unit tests Next section: Serving a frontend site »