# Flask with MongoDB

import { Tabs, TabsContent, TabsList, TabsTrigger } from "zudoku/ui/Tabs"

{/* vale off */}
{/* THIS FILE WAS AUTOGENERATED FROM THE PUBLIC EXAMPLE REPOSITORY. DO NOT EDIT THIS FILE DIRECTLY. */}


[Flask](https://flask.palletsprojects.com/en/stable/) is a lightweight WSGI web application framework in Python, and [MongoDB](https://www.mongodb.com/) is a NoSQL database that stores data in JSON-like documents.
This example deploys three services on Unikraft Cloud: NGINX (reverse proxy), Flask (backend), and MongoDB (database).

**Credits**: This example is based on this [Awesome Compose example](https://github.com/docker/awesome-compose/tree/master/nginx-flask-mongo).

## Deployment

To run this example, follow these steps:

1. Install the [unikraft CLI](/cli).
   You need a [BuildKit](https://github.com/moby/buildkit) builder. The easiest way to get one is via [Docker](https://docs.docker.com/engine/install/).
   Alternatively, you can also directly set up and use BuildKit, see the [quick start](https://github.com/moby/buildkit#quick-start).

2. Clone the [`examples` repository](https://github.com/unikraft-cloud/examples) and `cd` into the `examples/nginx-flask-mongo` directory:

   ```bash
   git clone https://github.com/unikraft-cloud/examples
   cd examples/nginx-flask-mongo/
   ```

Make sure to log into Unikraft Cloud and pick a [metro](/platform/metros) close to you.
This guide uses `fra` (Frankfurt, 🇩🇪):

```bash
unikraft login
```

## MongoDB

Create a volume for MongoDB data persistence:

```bash
unikraft volume create --metro fra --name mongo-data --size 1G
```

You can list the created volume by running:

```bash
unikraft volume list
```

```ansi
[1mMETRO[22m  [1mNAME[22m        [1mSTATE[22m      [1mSIZE[22m  [1mCREATED[22m
fra    mongo-data  [38;2;0;188;125mavailable[0m  1GiB  just now
```

First, deploy the MongoDB instance.
MongoDB is an internal service (not publicly accessible), reached via the `mongo.internal` domain:

```bash
unikraft build ./mongo --output <my-org>/mongo:latest
unikraft run --metro fra \
  -m 1024M \
  --scale-to-zero policy=idle,cooldown-time=1000,stateful=true \
  --domain mongo.internal \
  --volume mongo-data:/data/db \
  --image <my-org>/mongo:latest
```

The output shows the MongoDB instance details:

```ansi
[1mmetro[22m:           fra
[1mname[22m:            mongo-o3qhq
[1muuid[22m:            90158c53-6654-4e73-bad1-1d6ab4452001
[1mstate[22m:           [38;2;144;161;185mstarting[0m
[1mimage[22m:           <my-org>/mongo
[1mresources[22m:
[3m  memory[23m:        1GiB
[3m  vcpus[23m:         1
[1mservice[22m:
[3m  name[23m:          restless-glade-l8pu2mf0
[3m  uuid[23m:          77a04441-2479-433a-b468-32f23e475f58
[3m  domains[23m:
[3m  - fqdn[23m:        mongo.internal
[1mvolumes[22m:
[3m- name[23m:          mongo-data
[3m  uuid[23m:          9c7723f3-7e1f-4e06-afe6-c811240faf5a
[3m  at[23m:            /data/db
[1mnetworks[22m:
[3m- uuid[23m:          4f891227-d381-42f4-88a4-25a97b95a9e3
[3m  private-ip[23m:    10.0.15.21
[3m  mac[23m:           12:b0:0a:00:0f:15
[1mtimestamps[22m:
[3m  created[23m:       just now
[1mscale-to-zero[22m:
[3m  enabled[23m:       true
[3m  policy[23m:        idle
[3m  stateful[23m:      true
[3m  cooldown-time[23m: 1s
```

## Flask

Next, deploy the Flask backend.
It connects to MongoDB using the `MONGO_SERVER_URL` environment variable and is reached internally via `backend.internal`:

```bash
unikraft build ./flask --output <my-org>/flask:latest
unikraft run --metro fra \
  -m 1024M \
  --scale-to-zero policy=on,cooldown-time=1000 \
  --domain backend.internal \
  --env FLASK_SERVER_PORT=9091 \
  --env MONGO_SERVER_URL=mongo.internal:27017 \
  --image <my-org>/flask:latest
```

The output shows the Flask instance details:

```ansi
[1mmetro[22m:                 fra
[1mname[22m:                  flask-9a68z
[1muuid[22m:                  bb6d91f7-0714-45e5-b14a-ec82a5dac36e
[1mstate[22m:                 [38;2;144;161;185mstarting[0m
[1mimage[22m:                 <my-org>/flask
[1mruntime[22m:
[3m  env[23m:
    FLASK_SERVER_PORT: 9091
    MONGO_SERVER_URL:  mongo.internal:27017
[1mresources[22m:
[3m  memory[23m:              1GiB
[3m  vcpus[23m:               1
[1mservice[22m:
[3m  name[23m:                broken-bird-8isa6q21
[3m  uuid[23m:                cd9fe757-784a-49d4-8936-1b6859b3a72d
[3m  domains[23m:
[3m  - fqdn[23m:              backend.internal
[1mnetworks[22m:
[3m- uuid[23m:                2da7f679-7067-4fb5-908b-853607d383f2
[3m  private-ip[23m:          10.0.17.97
[3m  mac[23m:                 12:b0:0a:00:11:61
[1mtimestamps[22m:
[3m  created[23m:             just now
[1mscale-to-zero[22m:
[3m  enabled[23m:             true
[3m  policy[23m:              on
[3m  cooldown-time[23m:       1s
```

## NGINX

Finally, deploy NGINX as the public-facing reverse proxy.
It forwards requests to the Flask backend at `backend.internal:9091` by default.
To use a different backend domain, set the `BACKEND_HOST` environment variable to the same value you pass as the Flask domain.

```bash
unikraft build ./nginx --output <my-org>/nginx:latest
unikraft run --metro fra \
  -m 512M \
  -p 443:80/tls+http \
  --scale-to-zero policy=on,cooldown-time=1000 \
  -e BACKEND_HOST=backend.internal \
  --image <my-org>/nginx:latest
```

The output shows the NGINX instance details including its public FQDN:

```ansi
[1mmetro[22m:           fra
[1mname[22m:            nginx-jnpwi
[1muuid[22m:            57f64e99-bd06-46fd-98f4-26b64751623e
[1mstate[22m:           [38;2;144;161;185mstarting[0m
[1mimage[22m:           <my-org>/nginx
[1mresources[22m:
[3m  memory[23m:        512MiB
[3m  vcpus[23m:         1
[1mservice[22m:
[3m  name[23m:          snowy-river-gotjeojl
[3m  uuid[23m:          287ee3b8-43bc-47d1-a88e-4d6c72d2d682
[3m  domains[23m:
[3m  - fqdn[23m:        snowy-river-gotjeojl.fra.unikraft.app
[1mnetworks[22m:
[3m- uuid[23m:          107e4a03-e285-4d1d-84cb-24f86d7af875
[3m  private-ip[23m:    10.0.14.201
[3m  mac[23m:           12:b0:0a:00:0e:c9
[1mtimestamps[22m:
[3m  created[23m:       just now
[1mscale-to-zero[22m:
[3m  enabled[23m:       true
[3m  policy[23m:        on
[3m  cooldown-time[23m: 1s
```

You can list all deployed instances with:

```bash
unikraft instances list
```

```ansi
[1mMETRO[22m  [1mNAME[22m         [1mSTATE[22m    [1mIMAGE[22m           [1mMEMORY[22m  [1mVCPUS[22m  [1mFQDN[22m                                   [1mCREATED[22m
fra    nginx-jnpwi  [38;2;43;127;255mstandby[0m  <my-org>/nginx  512MiB  1      snowy-river-gotjeojl.fra.unikraft.app  11 minutes ago
fra    flask-9a68z  [38;2;43;127;255mstandby[0m  <my-org>/flask  1GiB    1      backend.internal                       12 minutes ago
fra    mongo-o3qhq  [38;2;43;127;255mstandby[0m  <my-org>/mongo  1GiB    1      mongo.internal                         14 minutes ago
```

## Test the deployment

The FQDN of the NGINX instance can be found in the `FQDN` column of the `unikraft instances list` output above.
Use `curl` to query it (replace with your actual FQDN):

```bash
curl https://<FQDN>
```

```text
Hello from the MongoDB client!
```

## Clean up

When done, remove the instances and volume:

```bash
unikraft instances delete mongo-o3qhq flask-9a68z nginx-jnpwi
unikraft volume delete mongo-data
```

## Learn more

Use the `--help` option for detailed information on using Unikraft Cloud:

```bash
unikraft --help
```

Or visit the [CLI Reference](/cli/unikraft).

- [Flask Documentation](https://flask.palletsprojects.com/en/stable/)
- [MongoDB Documentation](https://www.mongodb.com/docs/)
- [Nginx Documentation](https://nginx.org/en/docs/)
- [Awesome Compose](https://github.com/docker/awesome-compose)
- [Unikraft Cloud's Documentation](https://unikraft.cloud/docs/)
- [Building `Dockerfile` Images with `Buildkit`](https://unikraft.org/guides/building-dockerfile-images-with-buildkit)
{/* vale on */}
