Image and Build

Understanding the Basics

Before we jump into the TrueFoundry deployment process, let's quickly grasp some fundamental concepts.

  • Docker: Think of Docker as a tool that simplifies application development, packaging, and running. It allows you to bundle everything your application needs into a single unit called a Docker image, making it portable across different machines.
  • Docker Files and Images: A Docker file is like a recipe for creating a Docker image, which is a packaged version of your application with all its dependencies. These images are ready to run on any machine with Docker installed.
  • Docker Containers: These are like running instances of your Docker images, providing a consistent and isolated environment for your applications.

Introducing Kubernetes

While Docker containers are fantastic, managing them at scale poses challenges. This is where Kubernetes comes in.

  • Kubernetes: Picture Kubernetes as a powerful system for handling containerized applications. It automates tasks like deploying, scaling, and managing Docker containers across a group of machines.
  • Kubernetes Deployment Spec: To use Kubernetes, you specify details like the Docker image, the number of replicas (running instances), and allocated resources (CPU and memory) for each container. This information is crucial during application deployment.

TrueFoundry's Kubernetes Deployment Process

TrueFoundry streamlines the deployment process with a few key steps:

  1. Build your application: Write code, create a Docker file, and build a Docker image.
  2. Package your application: Upload your Docker image to TrueFoundry's registry.
  3. Ship your application: Craft a deployment manifest file detailing your application's deployment specifics.
  4. Deploy your application: Specify details like the Docker image, the number of replicas (running instances), and allocated resources (CPU and memory) using either the User Interface or the Python SDK
  5. Manage your application: TrueFoundry takes over, handling tasks like scaling, ensuring availability, and providing logs and metrics.

Steps 1, 2, and 3 are optional and can be managed by TrueFoundry if instructed. You can follow the documentation above to understand this more.

Different ways to deploy your applications in TrueFoundry

As explained above, When deploying your application, you'll need to specify the Docker Image containing your packaged application.

There can be three scenarios:

  • Pre-built Image: If you already have a pre-built Image, whether or not it's in your Docker Image Registry, you can directly deploy it. If not yet pushed, remember to upload it first.
  • Dockerfile Available: If you have a Dockerfile with instructions to build your Docker Image, you can provide the details of its location in your code. TrueFoundry will then handle the building and subsequent deployment.
  • No Image or Dockerfile Yet: If you're starting from scratch without an Image or Dockerfile, TrueFoundry can assist by gathering specifications about your Python code, such as command and Python version. It will then templatize a Dockerfile, create a Docker Image, and push it to the Docker Registry.

Regardless of the scenario, you end up with a Docker image. When TrueFoundry initiates a Replica/Pod for your deployment, it pulls this Docker image and runs it as a container.

πŸ“˜

Private Docker Registry

If you are using a Private Docker Registry, you will need to also integrate it with TrueFoundry.

TrueFoundry needs to access your Docker registry to save images built for deploying code or repositories and to deploy images from the registry to one of your connected workspaces. Integrate Docker Registry

Deploying your application when you have a Pre-built Image

Through User Interface

Through Python SDK

In your deployment code deploy.py, include the following:

from servicefoundry import Service, Image, Port

service = Service(
    name="your-service",
+    image = Image(
+      image_uri="your_image_uri",
# You can get this following this guide: https://docs.truefoundry.com/docs/integrations-docker-registry
+      docker_registry="your_docker_registry_fqn", 
+      command="command override",
+    )
    ports=[
      Port(
        host="your_host",
        port=8501
      )
    ],
)
service.deploy(workspace_fqn="YOUR_WORKSPACE_FQN")

Deploying your application when you don't have a Pre-built, but have a Docker File

Through User Interface

Through Python SDK

In your deployment code deploy.py, include the following:

from servicefoundry import Service, Build, DockerFileBuild, Port

service = Service(
    name="my-service",
+    image=Build(
+        build_spec=DockerFileBuild(
+            dockerfile_path="Dockerfile"
+            build_context_path="./",
+            build_args={
+            	"param": "value",
+             "param1": "value1",
+            },
+        ),
+		 )
    ports=[
      Port(
        host="your_host",
        port=8501
      )
    ],
)
service.deploy(workspace_fqn="YOUR_WORKSPACE_FQN")

πŸ“˜

Docker Build Args

In DockerFileBuild, use build_args to set arguments for docker build --build-arg. It involves key-value pairs of string datatype. For instance:

from servicefoundry import DockerFileBuild

build = DockerFileBuild(
    build_args={"FOO": "Hello", "BAR": "World!"}
)

The ARG instruction in Dockerfiles defines variables set at build-time with --build-arg during docker build. Here's a concise Dockerfile example:

FROM ubuntu

ARG FOO
ARG BAR

ENV FOO_ENV=$FOO
ENV BAR_ENV=$BAR

RUN echo $FOO_ENV && echo $BAR_ENV

Deploying your application when you don't have a Pre-built Image or a DockerFile

Through User Interface

Through Python SDK

In your deployment code deploy.py, include the following:

from servicefoundry import Service, Build, PythonBuild, Port

service = Service(
    name="your-service",
+    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"
+        ),
+    ),
    ports=[
      Port(
        host="your_host",
        port=8501
      )
    ],
)
service.deploy(workspace_fqn="YOUR_WORKSPACE_FQN")