When you deploy a job or service, you need to provide either a container image or build specification that servicefoundry uses to build an image. In this guide, we will go through the different concepts and components of the build specification.

A build specification is composed of two components.

  1. A build source. This defines the source code location.
  2. A build spec. This defines how to build a container image out of the build source.
from servicefoundry import Service, Build

service = Service(
    name="fastapi",
    image=Build(
        build_source=..., 
        build_spec=...,
    ),
    ...
)
name: fastapi
components:
  - name: fastapi
    type: service
    image:
      type: build
      build_source:
        ...
      build_spec:
        ...

Build source

A build source defines the source code location using which we will build a container image.

Local build source

You will need to use local build source if you want to deploy code present on your local machine (This can be your laptop, VM, CI environment, etc.). In this case, we copy the code present on your local directory to our build server.

from servicefoundry import Service, Build, LocalSource

service = Service(
    name="fastapi",
    image=Build(
        build_source=LocalSource(
            project_root_path="./my_project_root_path"
        ), 
        build_spec=...,
    ),
    ...
)
name: fastapi
components:
  - name: fastapi
    type: service
    image:
      type: build
      build_source:
        type: local
        project_root_path: "./my_project_root_path"
      build_spec:
        ...

Parameters

NameTypeDefault valueDescription
project_root_pathstring"./"The project root path. The contents of this directory will be uploaded to our build server to build the image.

Github build source

You can also use a public github repository as build source.

# We will use the `GithubSource` class here.
from servicefoundry import Service, Build, GithubSource

service = Service(
    name="fastapi",
    image=Build(
        build_source=GithubSource(
            repo_url="https://github.com/srihari-tf/tfy-demo",
            ref="main",
        ), 
        build_spec=...,
    ),
    ...
)
# The type: local identifies it as a local build source.
name: fastapi
components:
  - name: fastapi
    type: service
    image:
      type: build
      build_source:
        type: github
        repo_url: "https://github.com/srihari-tf/tfy-demo"
        ref: main
      build_spec:
        ...

Parameters

NameTypeDefault valueDescription
repo_urlstringThe public github repository link. We will clone this repo in our build servers to build the container image. This is a required parameter.
refstringThe commit sha, branch name or the tag to be used to build the image. This is a required parameter.

Build Spec

Our build servers use the build spec to build a container image from the source code defined using build source.

Dockerfile build

Use dockerfile build if you have already written a Dockerfile.

#We will use the `DockerFileBuild` class here.

from servicefoundry import Service, Build, DockerFileBuild

service = Service(
    name="fastapi",
    image=Build(
        build_spec=DockerFileBuild(
            dockerfile_path="Dockerfile"
            build_context_path="./",
            build_args={
            	"param": "value",
              "param1": "value1",
            },
        ),
    ),
    ...
)
name: fastapi
components:
  - name: fastapi
    type: service
    image:
      type: build
      build_source:
        type: local
      build_spec:
        type: dockerfile
        dockerfile_path: Dockerfile
        build_context_path: "./"
        build_args:
      		param: value
      		param1: value1

Parameters

NameTypeDefault valueDescription
dockerfile_pathstring"./Dockerfile"The file path of the Dockerfile relative to project/build source root path.
build_context_pathstring"./" (project/build source root path)Build context path for the Dockerfile relative to project/build source root path.
build_argsdictNoneBuild arguments to pass to --build-arg option in docker build.

Our build server uses this spec to build the container image using a command equivalent to,

docker build -f dockerfile_path build_context_path --build-arg param=value --build-arg param1=value1 ...

Python build

If you do not have a Dockerfile you can use the Python build to build a container image with a specific python version and pip packages installed.

from servicefoundry import Service, Build, PythonBuild

service = Service(
    name="fastapi",
    image=Build(
        build_spec=PythonBuild(
            python_version="3.9",
            build_context_path="./",
            requirements_path="my-requirements.txt",
            pip_packages=["fastapi==0.82.0", "uvicorn"],
            command="uvicorn main:app --port 8000 --host 0.0.0.0"
        ),
    ),
    ...
)
# type: tfy-python-buildpack` identifies it as a _Python build_. 
name: fastapi
components:
  - name: fastapi
    type: service
    image:
      type: build
      build_source:
        type: local
      build_spec:
        type: tfy-python-buildpack
        python_version: 3.9
        build_context_path: "./"
        requirements_path: my-requirements.txt
        pip_packages:
          - fastapi==0.82.0
          - uvicorn
        command: uvicorn main:app --port 8000 --host 0.0.0.0

Parameters

NameTypeDefault valueDescription
python_versionstring, regex: ^\d+(\.\d+){1,2}$"3.9"Python version to run your code. We use this to choose the base image.
build_context_pathstring"./" (project/build source root path)Build context path for the Dockerfile relative to project/build source root path.
requirements_pathstring, nullableNonePath to the requirements.txt file relative to project/build source root path. If there is file with the name requirements.txt under project root, we will automatically use that as the requirements_path.
pip_packagesList or array of stringsNoneAn array of pip package requirements.
commandstring or array of stringsCommand to run the code. This is a required argument.

NOTE: If you pass both requirements_path and pip_packages then we will install the union of the packages defined. IE: if you have fastapi defined in requirements.txt and pass ["numpy"] in pip_packages, we will install both numpy and fastapi.