Skip to content

Deployment package structure

Your deployment code needs to be packaged in the structure described below for the UbiOps platform to run it.

The packaged deployment is a zip file containing a number of required files and directories. This page specifies in what structure UbiOps expects your deployment file.

Deploying to UbiOps

Deployment package structure

Templates available on GitHub

Template structures are available for both Python and R on our Github. You can download an example Python deployment package .zip here: Download example deployment package.

Each deployment package should be uploaded to UbiOps as a ZIP archive. This ZIP can have any name. The ZIP must contain a directory, which can have any name, in the root of the ZIP. If your ZIP contains multiple directories, it will look for a directory called deployment_package. This directory should contain all deployment files.

The structure of the .zip package is similar for every language and needs to include the following:

deployment_folder.zip
        deployment_package/
                - deployment.py

                - requirements.txt (optional)
                - libraries/    (optional)
                - ubiops.yaml   (optional)
                - other files & artifacts (optional)
deployment_folder.zip
        deployment_package/
                - deployment.R

                - renv.lock or install_packages.R (optional)
                - ubiops.yaml   (optional)
                - other files & artifacts (optional)
  • A deployment file that contains the code which UbiOps will run each time a request is made.
  • (optional) Files containing package and library requirements that are installed and managed by UbiOps. For example, requirements.txt for Python and install_packages.R or renv.lock for R.
  • (optional) Files containing deployment artifacts and attributes. For instance, a model parameter file or pickle file.
  • (optional) A directory libraries where you can include dependencies that your deployment uses. This directory is added to the system $PATH variable, such that its contents can be easily imported.
  • (optional) A ubiops.yaml for installing anything on the Docker level. For more information see installing OS level packages.

Using the CLI to create the zip for you

You can also make use of the UbiOps command line interface to create the zip for you and upload it to reduce manual work.

Maximum deployment package size

The maximum size for a deployment package is 2 GiB.

Installing packages

  • requirements.txt - A list of Python packages required for the deployment. UbiOps will install the packages defined in this file for you using a fresh pip virtual environment once you upload your deployment. After this build step the dependencies are fixed and won't change. Read more about the requirements.txt file format and possibilities here.

  • libraries/ - directory where packages and system libraries are installed. This directory is added to the system $PATH variable.

  • A ubiops.yaml file for installing OS level packages in the container.

  • renv.lock - A lockfile containing packages required for the deployment. UbiOps will install the packages defined in this file for you using renv::restore() once you upload your deployment. For more information, take a look at renv documentation.

  • install_packages.R - An R file containing instructions to install packages, like, install.packages("randomForest"). After this build step the dependencies are fixed and won't change.

  • ubiops.yaml - A yaml file to install OS level packages in the container.

Preinstalled packages

To speed up the package installation process, some standard R packages are preinstalled:

All preinstalled packages

askpass, assertthat, backports, base64enc, BH, blob, broom, callr, cellranger, cli, clipr, colorspace, cpp11, crayon, curl, DBI, dbplyr, digest, dplyr, ellipsis, evaluate, fansi, farver, forcats, fs, generics, ggplot2, glue, gtable, haven, here, highr, hms, htmltools, httr, isoband, jsonlite, knitr, labeling, lifecycle, lubridate, magrittr, markdown, mime, modelr, munsell, openssl, pillar, pkgconfig, prettyunits, processx, progress, ps, purrr, R6, RColorBrewer, Rcpp, readr, readxl, rematch, remotes, renv, reprex, rlang, rmarkdown, rprojroot, rstudioapi, rvest, scales, selectr, stringi, stringr, sys, tibble, tidyr, tidyselect, tidyverse, tinytex, utf8, vctrs, viridisLite, withr, xfun, xml2, yaml

The deployment file

The deployment.py file or the deployment.R file needs to have the structure as shown below. They both contain an initialization method, which is called when the deployment is activated and a request method, which runs when a request to the deployment is received by UbiOps.

From here you can extend the code in any way you like.

"""
The file containing the deployment code is required to be called 'deployment.py' and should contain the 'Deployment'
class and 'request' method.
"""

# Always use absolute imports when importing modules from the deployment package directory. For example
# `import my_module` instead of `import .my_module`

import random


class Deployment:

    def __init__(self, base_directory, context):
    """
    Initialisation method for the deployment. It can for example be used for loading modules that have to be kept in
    memory or setting up connections. Load your external deployment files (such as pickles or .h5 files) here.
    :param str base_directory: absolute path to the directory where the deployment.py file is located
    :param dict context: a dictionary containing details of the deployment that might be useful in your code.
        It contains the following keys:
            - deployment (str): name of the deployment
            - version (str): name of the version
            - input_type (str): deployment input type, either 'structured' or 'plain'
            - output_type (str): deployment output type, either 'structured' or 'plain'
            - language (str): programming language the deployment is running
            - environment_variables (str): the custom environment variables configured for the deployment.
                You can also access those as normal environment variables via os.environ
    """

    print("Initialising My Deployment")

    def request(self, data):
    """
    Method for deployment requests, called separately for each individual request.
    :param dict/str data: request input data. In case of deployments with structured data, a Python dictionary
        with as keys the input fields as defined upon deployment creation via the platform. In case of a deployment
        with plain input, it is a string.
    :return dict/str: request output. In case of deployments with structured output data, a Python dictionary
        with as keys the output fields as defined upon deployment creation via the platform. In case of a deployment
        with plain output, it is a string. In this example, a dictionary with the key: output.
    """

    print("Processing request for My Deployment")

    # You can run any code to handle the request here.

    # For a structured deployment, we return a Python dict with output. In this example, we are assuming this
    # deployment receives one input field called 'input' and outputs one field called 'output'
    return {
        "output": data['input'] * random.random()
    }
# This file (containing the deployment code) is required to be called 'deployment.R' and should contain an 'init'
# and 'request' method.

#' @title Init
#' @description Initialisation method for the deployment.
#'     It can for example be used for loading modules that have to be kept in memory or setting up connections.
#' @param base_directory (str) absolute path to the directory where the deployment.R file is located
#' @param context (named list) details of the deployment that might be useful in your code
init <- function(base_directory, context) {
    print("Initialising My Deployment")
}


#' @title Request
#' @description Method for deployment requests, called separately for each individual request.
#' @param input_data (str or named list) request input data
#'     - In case of structured input: a named list, with as keys the input fields as defined upon deployment creation
#'     - In case of plain input: a string
#' @param base_directory (str) absolute path to the directory where the deployment.R file is located
#' @param context (named list) details of the deployment that might be useful in your code
#' @return output data (str or named list) request result
#'     - In case of structured output: a named list, with as keys the output fields as defined upon deployment creation
#'     - In case of plain output: a string
request <- function(input_data, base_directory, context) {
    print("Processing request for My Deployment")


    # ADD YOUR CODE HERE...


    # Another script can be called using: source(file.path(base_directory, "<script name>.R"))
    # Environment variables can be obtained via: Sys.getenv("ENV_VAR", unset = "")


    # In this example, the input field "input" in multiplied by a random number and returned in output field "output"
    list( output = input_data[["input"]] * runif(1) )
}

Input and output of the request function

The request method has an input variable called data. This object will contain the data payload for each request. After processing, the request function will also return an output.

More details on how to handle the input and output of the request function and what data types can be used, can be found in the Deployment In- and output section.
There you can also find examples on how to work with files or how to convert well-known Python data structures like NumPy Arrays and Pandas DataFrames to data-types that UbiOps can work with.

Read more ->

Testing your deployment

The deployment template in our Github project contains an example script to test whether your deployment is working correctly within our deployment wrapper.

Edit and execute the file run_deployment.py (or run_deployment.R) according to your deployment to simulate the UbiOps back-end that initializes the deployment and makes a request.