App

Runtimes

Technical reference on runtimes available in the Nextmv Platform.

When an app is deployed, a runtime is provisioned for it. Runtimes are defined by Docker images. The runtime provides the environment in which the app runs.

These runtimes are provisioned on Linux ARM64 machines in Nextmv.

The cuopt runtime is provisioned on Linux AMD64 with an attached NVIDIA GPU. It is capable of running models using NVIDIA cuOpt.

You may also pull these images down and use them for local development, for example:

cat input.json | \
    docker run --rm -i -v $(pwd):/app ghcr.io/nextmv-io/runtime/python:3.11 \
    python main.py
Copy

If you need packages that are not already included in a runtime, please contact Nextmv support.

ghcr.io/nextmv-io/runtime/default

This runtime is used to run compiled applications such as Go binaries.

  • Versions:

    • ghcr.io/nextmv-io/runtime/default:latest
  • Languages:

    • Go
  • Dockerfile:

FROM debian:trixie-slim

# Set a default working directory.
WORKDIR /app

# Install certificates.
RUN apt update && apt install -y ca-certificates
Copy
  • Examples of app.yaml manifests in community apps that use this runtime:
# This manifest holds the information the app needs to run on the Nextmv Cloud.
type: go
runtime: ghcr.io/nextmv-io/runtime/default:latest

# Directives to build a Go binary from the app.
build:
  command: go build -o main .
  environment:
    GOOS: linux
    GOARCH: arm64

# List all files/directories that should be included in the app. Globbing
# (e.g.: configs/*.json) is supported.
files:
  - main

configuration:
  options:
    strict: false
    validation:
      enforce: all
    items:
      # Check options
      - name: check.duration
        option_type: string
        description: "Maximum duration of the check (e.g.: '30s', '5m')"
        ui:
          control_type: input
          display_name: Check Duration
      - name: check.verbosity
        option_type: string
        description: "{off, low, medium, high} verbosity of the check"
        additional_attributes:
          values:
            - "off"
            - "low"
            - "medium"
            - "high"
        ui:
          control_type: select
          display_name: Check Verbosity

      # Format options
      - name: format.disable.progression
        option_type: bool
        description: Disable the progression series
        ui:
          control_type: toggle
          display_name: Disable Progression
          hidden_from:
            - viewer
            - operator

      # Model constraint disable options
      - name: model.constraints.disable.attributes
        option_type: bool
        description: Ignore the compatibility attributes constraint
        ui:
          control_type: toggle
          display_name: Disable Attributes Constraint
      - name: model.constraints.disable.capacities
        option_type: string
        description: "Ignore the capacity constraint for the given resource names (e.g.: 'weight,volume')"
        ui:
          control_type: input
          display_name: Disable Specific Capacities
      - name: model.constraints.disable.capacity
        option_type: bool
        description: Ignore the capacity constraint for all resources
        ui:
          control_type: toggle
          display_name: Disable All Capacity Constraints
      - name: model.constraints.disable.distancelimit
        option_type: bool
        description: Ignore the distance limit constraint
        ui:
          control_type: toggle
          display_name: Disable Distance Limit
      - name: model.constraints.disable.groups
        option_type: bool
        description: Ignore the groups constraint
        ui:
          control_type: toggle
          display_name: Disable Groups Constraint
      - name: model.constraints.disable.maximumduration
        option_type: bool
        description: Ignore the maximum duration constraint
        ui:
          control_type: toggle
          display_name: Disable Maximum Duration
      - name: model.constraints.disable.maximumstops
        option_type: bool
        description: Ignore the maximum stops constraint
        ui:
          control_type: toggle
          display_name: Disable Maximum Stops
      - name: model.constraints.disable.maximumwaitstop
        option_type: bool
        description: Ignore the maximum stop wait constraint
        ui:
          control_type: toggle
          display_name: Disable Maximum Wait Stop
      - name: model.constraints.disable.maximumwaitvehicle
        option_type: bool
        description: Ignore the maximum vehicle wait constraint
        ui:
          control_type: toggle
          display_name: Disable Maximum Wait Vehicle
      - name: model.constraints.disable.mixingitems
        option_type: bool
        description: Ignore the do not mix items constraint
        ui:
          control_type: toggle
          display_name: Disable Mixing Items
      - name: model.constraints.disable.precedence
        option_type: bool
        description: Ignore the precedence (pickups & deliveries) constraint
        ui:
          control_type: toggle
          display_name: Disable Precedence
      - name: model.constraints.disable.starttimewindows
        option_type: bool
        description: Ignore the start time windows constraint
        ui:
          control_type: toggle
          display_name: Disable Start Time Windows
      - name: model.constraints.disable.vehicleendtime
        option_type: bool
        description: Ignore the vehicle end time constraint
        ui:
          control_type: toggle
          display_name: Disable Vehicle End Time
      - name: model.constraints.disable.vehiclestarttime
        option_type: bool
        description: Ignore the vehicle start time constraint
        ui:
          control_type: toggle
          display_name: Disable Vehicle Start Time

      # Model constraint enable options
      - name: model.constraints.enable.cluster
        option_type: bool
        description: Enable the cluster constraint
        ui:
          control_type: toggle
          display_name: Enable Cluster Constraint

      # Model objectives
      - name: model.objectives.capacities
        option_type: string
        description: "Capacity objective, provide triple for each resource 'name=default;factor=1.0;offset=0.0'"
        ui:
          control_type: input
          display_name: Capacities Objective
      - name: model.objectives.cluster
        option_type: float
        description: "Factor to weigh the cluster objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Cluster Objective
      - name: model.objectives.distance
        option_type: float
        description: "Factor to weigh the travel distance objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Distance Objective
      - name: model.objectives.earlyarrivalpenalty
        option_type: float
        description: "Factor to weigh the early arrival objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Early Arrival Penalty
      - name: model.objectives.latearrivalpenalty
        option_type: float
        description: "Factor to weigh the late arrival objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Late Arrival Penalty
      - name: model.objectives.minstops
        option_type: float
        description: "Factor to weigh the min stops objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Min Stops Objective
      - name: model.objectives.stopbalance
        option_type: float
        description: "Factor to weigh the stop balance objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Stop Balance Objective
      - name: model.objectives.travelduration
        option_type: float
        description: "Factor to weigh the travel duration objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Travel Duration Objective
      - name: model.objectives.unplannedpenalty
        option_type: float
        description: "Factor to weigh the unplanned objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Unplanned Penalty
      - name: model.objectives.vehicleactivationpenalty
        option_type: float
        description: "Factor to weigh the vehicle activation objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Vehicle Activation Penalty
      - name: model.objectives.vehiclesduration
        option_type: float
        description: "Factor to weigh the vehicles duration objective (e.g.: 2.0)"
        ui:
          control_type: input
          display_name: Vehicles Duration Objective

      # Model properties
      - name: model.properties.disable.durationgroups
        option_type: bool
        description: Ignore the durations groups of stops
        ui:
          control_type: toggle
          display_name: Disable Duration Groups
      - name: model.properties.disable.durations
        option_type: bool
        description: Ignore the durations of stops
        ui:
          control_type: toggle
          display_name: Disable Durations
      - name: model.properties.disable.initialsolution
        option_type: bool
        description: Ignore the initial solution
        ui:
          control_type: toggle
          display_name: Disable Initial Solution
      - name: model.properties.disable.stopdurationmultipliers
        option_type: bool
        description: Ignore the stop duration multipliers defined on vehicles
        ui:
          control_type: toggle
          display_name: Disable Stop Duration Multipliers
      - name: model.properties.maximumtimehorizon
        option_type: int
        description: "Maximum time horizon for the model in seconds (e.g.: 604800)"
        ui:
          control_type: input
          display_name: Maximum Time Horizon
          hidden_from:
            - viewer
            - operator

      # Model validation
      - name: model.validate.disable.resources
        option_type: bool
        description: Disable the resources validation
        ui:
          control_type: toggle
          display_name: Disable Resources Validation
          hidden_from:
            - viewer
            - operator
      - name: model.validate.disable.starttime
        option_type: bool
        description: Disable the start time validation
        ui:
          control_type: toggle
          display_name: Disable Start Time Validation
          hidden_from:
            - viewer
            - operator
      - name: model.validate.enable.matrix
        option_type: bool
        description: Enable matrix validation
        ui:
          control_type: toggle
          display_name: Enable Matrix Validation
          hidden_from:
            - viewer
            - operator
      - name: model.validate.enable.matrixasymmetrytolerance
        option_type: int
        description: "Percentage of acceptable matrix asymmetry, requires matrix validation enabled (e.g.: 10 - for 10%)"
        ui:
          control_type: input
          display_name: Matrix Asymmetry Tolerance
          hidden_from:
            - viewer
            - operator

      # Runner options
      - name: runner.input.path
        option_type: string
        description: The input file path
        ui:
          control_type: input
          display_name: Input Path
          hidden_from:
            - viewer
            - operator
      - name: runner.output.path
        option_type: string
        description: The output file path
        ui:
          control_type: input
          display_name: Output Path
          hidden_from:
            - viewer
            - operator
      - name: runner.output.solutions
        option_type: string
        description: "{all, last} specifies whether to output all solutions or only the last one"
        additional_attributes:
          values:
            - "all"
            - "last"
        ui:
          control_type: select
          display_name: Output Solutions
          hidden_from:
            - viewer
            - operator
      - name: runner.profile.cpu
        option_type: string
        description: The CPU profile file path
        ui:
          control_type: input
          display_name: CPU Profile Path
          hidden_from:
            - viewer
            - operator
      - name: runner.profile.memory
        option_type: string
        description: The memory profile file path
        ui:
          control_type: input
          display_name: Memory Profile Path
          hidden_from:
            - viewer
            - operator

      # Solve options
      - name: solve.duration
        option_type: string
        description: "Maximum duration of the solver (e.g.: '30s', '5m')"
        ui:
          control_type: input
          display_name: Solve Duration
      - name: solve.iterations
        option_type: int
        description: "Maximum number of iterations, -1 assumes no limit; iterations are counted after start solutions are generated (e.g.: 100000)"
        ui:
          control_type: input
          display_name: Solve Iterations
          hidden_from:
            - viewer
            - operator
      - name: solve.parallelruns
        option_type: int
        description: "Maximum number of parallel runs, -1 results in using all available resources (e.g.: 4)"
        ui:
          control_type: input
          display_name: Parallel Runs
          hidden_from:
            - viewer
            - operator
      - name: solve.plateau.absolutethreshold
        option_type: float
        description: "Absolute threshold for significant improvement (e.g.: 1000.0)"
        ui:
          control_type: input
          display_name: Plateau Absolute Threshold
      - name: solve.plateau.delay
        option_type: string
        description: "Delay before plateau detection starts (e.g.: '30s', '5m')"
        ui:
          control_type: input
          display_name: Plateau Delay
      - name: solve.plateau.duration
        option_type: string
        description: "Maximum duration without (significant) improvement before solver stops itself (e.g.: '30s', '5m')"
        ui:
          control_type: input
          display_name: Plateau Duration
      - name: solve.plateau.iterations
        option_type: int
        description: "Maximum number of iterations without (significant) improvement before solver stops itself (e.g.: 10000)"
        ui:
          control_type: input
          display_name: Plateau Iterations
      - name: solve.plateau.relativethreshold
        option_type: float
        description: "Relative threshold for significant improvement (e.g.: 0.01 for 1%)"
        ui:
          control_type: input
          display_name: Plateau Relative Threshold
      - name: solve.rundeterministically
        option_type: bool
        description: Run the parallel solver deterministically
        ui:
          control_type: toggle
          display_name: Run Deterministically
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.plangroupsize.delta
        option_type: int
        description: "Delta is the initial change in value after a number of iterations without improvement (e.g.: 0). This is used to adjust the group size of the plan operator during solving."
        ui:
          control_type: input
          display_name: Plan Group Size Delta
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.plangroupsize.deltaafteriterations
        option_type: int
        description: "Number of iterations without improvement after which the value is changed (e.g.: 1000000000). This is used to adjust the group size of the plan operator during solving."
        ui:
          control_type: input
          display_name: Plan Group Size Delta After Iterations
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.plangroupsize.maxvalue
        option_type: int
        description: "Maximum value for the group size (e.g.: 2). This is used to adjust the group size of the plan operator during solving."
        ui:
          control_type: input
          display_name: Plan Group Size Max Value
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.plangroupsize.minvalue
        option_type: int
        description: "Minimum value for the group size (e.g.: 2). This is used to adjust the group size of the plan operator during solving."
        ui:
          control_type: input
          display_name: Plan Group Size Min Value
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.plangroupsize.snapbackafterimprovement
        option_type: bool
        description: "Snap back to the start value after an improvement is found. This is used to adjust the group size of the plan operator during solving."
        ui:
          control_type: toggle
          display_name: Plan Group Size Snap Back After Improvement
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.plangroupsize.startvalue
        option_type: int
        description: "Starting value for the group size (e.g.: 2). This is used to adjust the group size of the plan operator during solving."
        ui:
          control_type: input
          display_name: Plan Group Size Start Value
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.plangroupsize.zigzag
        option_type: bool
        description: "Zigzag is a flag that indicates if the value should zigzag between the min and max value. This is used to adjust the group size of the plan operator during solving."
        ui:
          control_type: toggle
          display_name: Plan Group Size Zigzag
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanunits.delta
        option_type: int
        description: "Delta is the initial change in value after a number of iterations without improvement (e.g.: 2). This is used to adjust the number of units for the unplan operator during solving."
        ui:
          control_type: input
          display_name: Unplan Units Delta
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanunits.deltaafteriterations
        option_type: int
        description: "Number of iterations without improvement after which the value is changed (e.g.: 125). This is used to adjust the number of units for the unplan operator during solving."
        ui:
          control_type: input
          display_name: Unplan Units Delta After Iterations
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanunits.maxvalue
        option_type: int
        description: "Maximum value for the number of units (e.g.: -1). This is used to adjust the number of units for the unplan operator during solving. -1 auto-configures to a fraction of the total number of stops."
        ui:
          control_type: input
          display_name: Unplan Units Max Value
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanunits.minvalue
        option_type: int
        description: "Minimum value for the number of units (e.g.: 2). This is used to adjust the number of units for the unplan operator during solving."
        ui:
          control_type: input
          display_name: Unplan Units Min Value
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanunits.snapbackafterimprovement
        option_type: bool
        description: "Snap back to the start value after an improvement is found. This is used to adjust the number of units for the unplan operator during solving."
        ui:
          control_type: toggle
          display_name: Unplan Units Snap Back After Improvement
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanunits.startvalue
        option_type: int
        description: "Starting value for the number of units (e.g.: 2). This is used to adjust the number of units for the unplan operator during solving."
        ui:
          control_type: input
          display_name: Unplan Units Start Value
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanunits.zigzag
        option_type: bool
        description: "Zigzag is a flag that indicates if the value should zigzag between the min and max value. This is used to adjust the number of units for the unplan operator during solving."
        ui:
          control_type: toggle
          display_name: Unplan Units Zigzag
          hidden_from:
            - viewer
            - operator
      - name: solve.solver.unplanweights
        option_type: string
        description: "Comma separated list of weights for unplanning strategies (e.g.: 'Vehicle:3,Island:1,Location:300')"
        ui:
          control_type: input
          display_name: Unplan Weights
          hidden_from:
            - viewer
            - operator
      - name: solve.startsolutions
        option_type: int
        description: "Number of solutions to generate on top of those passed in; one solution generated with sweep algorithm, the rest generated randomly (e.g.: 5)"
        ui:
          control_type: input
          display_name: Start Solutions
          hidden_from:
            - viewer
            - operator

  # Specify the format the app reads and writes.
  content:
    format: "json" # Read JSON from stdin and write JSON to stdout.
Copy

ghcr.io/nextmv-io/runtime/python

This runtime is used as the basis for other Python runtimes.

  • Versions:

    • ghcr.io/nextmv-io/runtime/python:3.11
  • Languages:

    • Python
  • Dockerfile:

FROM python:3.11-slim

# Set a default working directory
WORKDIR /app
Copy
  • Examples of app.yaml manifests in community apps that use this runtime:
# This manifest holds the information the app needs to run on the Nextmv Cloud.
type: python
runtime: ghcr.io/nextmv-io/runtime/python:3.11
python:
  # All listed packages will get bundled with the app.
  pip-requirements: requirements.txt

# List all files/directories that should be included in the app. Globbing
# (e.g.: configs/*.json) is supported.
files:
  - main.py
  - visuals.py

configuration:
  # Specify the format the app reads and writes.
  content:
    format: "json" # Read JSON from stdin and write JSON to stdout.
Copy

ghcr.io/nextmv-io/runtime/java

This runtime is used to run Java applications.

  • Versions:

    • ghcr.io/nextmv-io/runtime/java:latest
  • Languages:

    • Java
  • Dockerfile:

FROM eclipse-temurin:21-jdk-noble

# Define some default paths for dynamic libraries
ENV LD_LIBRARY_PATH=.:./lib

# Define a default location for a gurobi license file
ENV GRB_LICENSE_FILE=./gurobi.lic

# Set a default working directory
WORKDIR /app
Copy
  • Examples of app.yaml manifests in community apps that use this runtime:
# This manifest holds the information the app needs to run on the Nextmv Cloud.
type: java
runtime: ghcr.io/nextmv-io/runtime/java:latest

# Directives to compile a binary from the app.
pre-push: mvn package

# List all files/directories that should be included in the app. Globbing
# (e.g.: configs/*.json) is supported.
files:
  - main.jar

configuration:
  # Specify the format the app reads and writes.
  content:
    format: "json" # Read JSON from stdin and write JSON to stdout.
Copy

ghcr.io/nextmv-io/runtime/pyomo

This runtime provisions Python packages to run Pyomo applications. It also installs solvers, such as GLPK and CBC.

  • Versions:

    • ghcr.io/nextmv-io/runtime/pyomo:latest
  • Languages:

    • Python
  • Dockerfile:

FROM python:3.11-slim

# Set a default working directory.
WORKDIR /app

# Update the package list.
RUN apt-get update

# Install cbc solver.
RUN apt-get install -y \
    coinor-cbc \
    coinor-libcbc-dev

# Install glpk solver.
RUN apt-get install -y glpk-utils

# Install SCIP solver.
## Install requirements.
RUN apt-get install -y \
    wget \
    gcc \
    g++ \
    gfortran \
    liblapack3 \
    libtbb12 \
    libcliquer1 \
    libopenblas-dev \
    libgsl28 \
    patchelf \
    cmake \
    wget \
    m4 \
    xz-utils \
    libgmp-dev \
    unzip \
    zlib1g-dev \
    libboost-program-options-dev \
    libboost-serialization-dev \
    libboost-regex-dev \
    libboost-iostreams-dev \
    libtbb-dev \
    libreadline-dev \
    pkg-config \
    git \
    liblapack-dev \
    libgsl-dev \
    flex \
    bison \
    libcliquer-dev \
    gfortran \
    file \
    dpkg-dev \
    libopenblas-dev \
    rpm

## Download the source code.
ENV SCIP_VERSION=9.1.1
ENV SCIP_DIR=scip-\${SCIP_VERSION}
ENV SCIP_TAR=\${SCIP_DIR}.tgz
RUN wget https://scipopt.org/download/release/\${SCIP_TAR}

## Install the SCIP solver (https://www.scipopt.org/doc/html/md_INSTALL.php).
RUN tar xvzf \${SCIP_TAR} && \
    cd \${SCIP_DIR} && \
    mkdir build && \
    cd build && \
    ls -lah && \
    cmake .. -DAUTOBUILD=on -DCMAKE_INSTALL_PREFIX=/usr && \
    make && \
    make check && \
    make install && \
    cp -r bin/* /usr/bin && \
    cp -r lib/* /usr/lib

# Install requirements.
COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

# Clean up.
RUN rm \${SCIP_TAR}
RUN rm -rf \${SCIP_DIR}
Copy
  • requirements.txt installed in the runtime:
# Pyomo packages.
pyomo==6.6.2

# Other packages.
numpy==1.26.4
pandas==2.2.0
scipy==1.12.0
Copy
  • Examples of app.yaml manifests in community apps that use this runtime:
# This manifest holds the information the app needs to run on the Nextmv Cloud.
type: python
runtime: ghcr.io/nextmv-io/runtime/pyomo:latest
# List all files/directories that should be included in the app. Globbing
# (e.g.: configs/*.json) is supported.
files:
  - main.py
python:
  # Packages the app depends on need to be listed in a requirements.txt file
  # that is referenced here. All listed packages will get bundled with the app.
  pip-requirements: requirements.txt

configuration:
  # Specify the format the app reads and writes.
  content:
    format: "json" # Read JSON from stdin and write JSON to stdout.
Copy

ghcr.io/nextmv-io/runtime/cuopt

This runtime is contains Python, CUDA libraries, and NVIDIA cuOpt.

  • Versions:

    • ghcr.io/nextmv-io/runtime/cuopt:latest
  • Languages:

    • Python
  • Dockerfile:

FROM nvidia/cuopt:25.10.0a-cuda12.9-py3.12

# python3 should be python3.12, not python3.10
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 312

# Set a default working directory
WORKDIR /app
Copy
  • Examples of app.yaml manifests in community apps that use this runtime:
# This manifest holds the information the app needs to run on the Nextmv Cloud.
type: python
runtime: ghcr.io/nextmv-io/runtime/cuopt:latest

python:
  # All listed packages will get bundled with the app.
  pip-requirements: requirements.txt
  arch: amd64 # Nextmv Cloud runs cuOpt models on amd64 instances.
  version: 3.12 # The cuOpt image uses Python 3.12.

# List all files/directories that should be included in the app. Globbing
# (e.g.: configs/*.json) is supported.
files:
  - main.py
  - visual.py

configuration:
  # Specify the format the app reads and writes.
  content:
    format: "json" # Read JSON from stdin and write JSON to stdout.
Copy

Page last updated

Go to on-page nav menu