> ## Documentation Index
> Fetch the complete documentation index at: https://anaconda.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing your first deployment

This tutorial walks you through deploying a long-running service on Anaconda Platform: a minimal Flask app packaged with its dependencies, configured with a YAML file, and launched with the CLI. To deploy a model from the model catalog instead, see [Deploy a model from the model catalog](https://anaconda.com/docs/platform/guides/inference/deploy-model-from-catalog.md).

## A "hello world" deployment

For this tutorial, assume you have a simple Flask service:

* my-first-project/
  * first-service.py

The code for `first-service.py`:

```python expandable theme={null}
from flask import Flask
import os
import time

app = Flask(__name__)


@app.route("/")
def hello_world():
    return {"message": "Hello, World!"}


if __name__ == "__main__":
    port = int(os.environ.get("PORT", 8000))
    app.run(host="0.0.0.0", port=port)
```

## Managing requirements

The platform automatically packages your dependencies into a Docker container to run your deployment, just like Metaflow tasks.

You can declare dependencies in a few different formats. One of the easiest is a `requirements.txt` file at the root of your project. For all the ways to manage dependencies, see [Dependency management](https://anaconda.com/docs/platform/guides/inference/deployments-deep-dive.md#dependency-management).

For this example, create a `requirements.txt` that specifies the one dependency, `flask`:

* my-first-project/
  * first-service.py
  * requirements.txt

## Defining a config file

You can configure the behavior of your deployment either by passing options to the CLI or by creating a config file. Anaconda recommends defining as much configuration as possible in the config file, and using CLI options occasionally to override the config file or for rapid prototyping.

Create a config file called `config.yaml`:

```yaml theme={null}
name: hello-world 
port: 8000
auth:
  type: API

commands: 
- python first-service.py
```

Place it in the root of your project:

* my-first-project/
  * first-service.py
  * requirements.txt
  * config.yaml

## Deploying your service

With the service code and dependencies ready, deploy the service:

```sh theme={null}
outerbounds app deploy --config-file config.yaml
```

The command packages your code, builds a container image with your dependencies, provisions the workers, and exposes the service. The output ends with the URL of your deployed endpoint:

```text expandable theme={null}
     🚀 Deploying hello-world to the platform...
     📦 Packaging directories: my-first-project/
     📦 Using dependencies from requirements.txt: my-first-project/requirements.txt
     🍳 Baking [hello-world] ...
          🐍 Python: 3.9.12
          📦 PyPI packages:
             🔧 flask: 3.0.2
     🏁 Baked [hello-world] in 44.05 seconds!
     🚀 Upgrading endpoint `hello-world`...
     ⏳ 1 new worker(s) pending
     🚀 1 worker(s) started running
     ✅ First worker came online
     🎉 All workers are now running
     💊 Endpoint hello-world is ready to serve traffic on the URL: https://api-c-3si29v.example.com
```

### Understanding the deploy command

> [accordion] Full breakdown of the deploy command and config file
>
> Command options:
>
> * `app deploy` deploys a new deployment or updates an existing one.
> * `--config-file` defines the location of the config file that contains the configuration for your deployment.
>
> Config file fields:
>
> * `name` is the globally unique identifier of your deployment. No two deployments can have the same name.
> * `port` is the port number where your service listens. In the Flask example above, the server starts on port 8000, so the config passes the same port.
> * `auth.type` takes two values:
>   * `API`: token-based authentication for programmatic clients such as cURL or Python scripts. See [Accessing your deployed endpoint](#accessing-your-deployed-endpoint) for an example.
>   * `Browser`: the endpoint uses the same SSO authentication as the platform. Anyone signed in to the platform can access it.
> * `commands` is the command used to launch your service: the same command you would use to run the service locally. In this example, `python first-service.py`. You can provide multiple commands if needed.

## Accessing your deployed endpoint

You can construct a request for your endpoint with cURL, Python, or the language of your choice. The only additional requirement is attaching auth headers to your request so the platform can authenticate it.

If you have `metaflow` in your environment already, use the following snippet to generate the headers for your call:

```python theme={null}
def get_auth_headers():
    from metaflow.metaflow_config_funcs import init_config
    conf = init_config()
    if conf:
        headers = {'x-api-key': conf['METAFLOW_SERVICE_AUTH_KEY']}
    else:
        headers = json.loads(os.environ['METAFLOW_SERVICE_HEADERS'])
    return headers
```

If you are calling the endpoint from an external environment that does not have `metaflow` installed, use the lightweight `ob-auth` package instead:

```sh theme={null}
pip install ob-auth
```

```python theme={null}
def get_auth_headers(): 
    from ob_auth import OuterboundsAuth
    auth = OuterboundsAuth()
    auth.init_from_config()
    return auth.api_headers()
```

Use either function to call your deployed endpoint, replacing the URL with the URL of your deployment:

```python theme={null}
import requests
import os

url = "<ENDPOINT_URL>"
print(requests.get(url, headers=get_auth_headers()).text)
```

Comments

Replace \<ENDPOINT\_URL> with the URL printed at the end of the deploy command output, or the "available at" URL shown in the deployment details view.

The `get_auth_headers()` function works in all of the following cases:

* Running locally from a script when you have a Metaflow config.
* Running from inside a local or remote Metaflow task.
* Running from any environment where you have a machine user configured. If you use `ob-auth` with an IAM machine user, install it with `pip install ob-auth[aws]`.

## Up next

* For a deeper understanding of working with deployments, see [Deployments deep dive](https://anaconda.com/docs/platform/guides/inference/deployments-deep-dive.md).
* To manage deployments from the command line, see the [Deployments CLI reference](https://anaconda.com/docs/platform/cli/app/deploy.md).
