# Source: https://github.com/jina-ai/jina/blob/master/docs/cloud-nativeness/docker-compose.md

(docker-compose)=

# {fab}`docker` Docker Compose Support

One of the simplest ways to prototype or serve in
production is to run your {class}`~jina.Flow` with `docker-compose`.

A {class}`~jina.Flow` is composed of {class}`~jina.Executor`s which run Python code
that operates on `Documents`. These `Executors` live in different runtimes depending on how you want to deploy
your Flow.

By default, if you are serving your Flow locally they live within processes. Nevertheless,
because Jina-serve is cloud native your Flow can easily manage Executors that live in containers and that are
orchestrated by your favorite tools. One of the simplest is Docker Compose which is supported out of the box.

You can deploy a Flow with Docker Compose in one line:


```{code-block} python
---
emphasize-lines: 3
---
from jina import Flow
flow = Flow(...).add(...).add(...)
flow.to_docker_compose_yaml('docker-compose.yml')
```

Jina-serve generates a `docker-compose.yml` configuration file corresponding with your Flow. You can use this directly with
Docker Compose, avoiding the overhead of manually defining all of your Flow's services.

````{admonition} Use Docker-based Executors
:class: caution
All Executors in the Flow should be used with `jinaai+docker://...` or `docker://...`.
````

````{admonition} Health check available from 3.1.3
:class: caution
If you use Executors that rely on Docker images built with a version of Jina-serve prior to 3.1.3, remove the 
health check from the dumped YAML file, otherwise your Docker Compose services will 
always be "unhealthy."
````

````{admonition} Matching Jina-serve versions
:class: caution
If you change the Docker images in your Docker Compose generated file, ensure that all services included in
the Gateway are built with the same Jina-serve version to guarantee compatibility.
````

## Example: Index and search text using your own built Encoder and Indexer

Install [`Docker Compose`](https://docs.docker.com/compose/install/) locally before starting this tutorial.

For this example we recommend that you read {ref}`how to build and containerize the Executors to be run in Kubernetes. <build-containerize-for-k8s>`

### Deploy the Flow

First define the Flow and generate the Docker Compose YAML configuration:


````{tab} YAML
In a `flow.yml` file :
```yaml
jtype: Flow
with:
  port: 8080
  protocol: http
executors:
- name: encoder
  uses: jinaai+docker://<user-id>/EncoderPrivate
  replicas: 2
- name: indexer
  uses: jinaai+docker://<user-id>/IndexerPrivate
  shards: 2
```
Then in a shell run:
```shell
jina export docker-compose flow.yml docker-compose.yml 
```
````


````{tab} Python
In python run
```python
from jina import Flow

flow = (
    Flow(port=8080, protocol='http')
    .add(name='encoder', uses='jinaai+docker://<user-id>/EncoderPrivate', replicas=2)
    .add(
        name='indexer',
        uses='jinaai+docker://<user-id>/IndexerPrivate',
        shards=2,
    )
)
flow.to_docker_compose_yaml('docker-compose.yml')
```
````

````{admonition} Hint
:class: hint
You can use a custom jina Docker image for the Gateway service by setting the environment variable `JINA_GATEWAY_IMAGE` to the desired image before generating the configuration.
````

let's take a look at the generated compose file:

```yaml
version: '3.3'
...
services:
  encoder-rep-0:  # # # # # # # # # # #          
                  #     Encoder       #
  encoder-rep-1:  # # # # # # # # # # #

  indexer-head:   # # # # # # # # # # #          
                  #                   #
  indexer-0:      #     Indexer       #
                  #                   #
  indexer-1:      # # # # # # # # # # #

  gateway: 
    ...
    ports:
    - 8080:8080
```

```{tip}
:class: caution
The default compose file generated by the Flow contains no special configuration or settings. You may want to
adapt it to your own needs.
```

You can see that six services are created:

- 1 for the **Gateway** which is the entrypoint of the **Flow**.
- 2 associated with the encoder for the two Replicas.
- 3 associated with the indexer, one for the Head and two for the Shards.

Now, you can deploy this Flow :

```shell
docker-compose -f docker-compose.yml up
```

### Query the Flow

Once we see that all the services in the Flow are ready, we can send index and search requests.

First define a client:

```python
from jina.clients import Client

client = Client(host='http://localhost:8080')
```

```python
from typing import List, Optional
from docarray import DocList, BaseDoc
from docarray.typing import NdArray


class MyDoc(BaseDoc):
    text: str
    embedding: Optional[NdArray] = None


class MyDocWithMatches(MyDoc):
    matches: DocList[MyDoc] = []
    scores: List[float] = []

docs = client.post(
    '/index',
    inputs=DocList[MyDoc]([MyDoc(text=f'This is document indexed number {i}') for i in range(100)]),
    return_type=DocList[MyDoc],
    request_size=10
)

print(f'Indexed documents: {len(docs)}')
docs = client.post(
    '/search',
    inputs=DocList[MyDoc]([MyDoc(text=f'This is document query number {i}') for i in range(10)]),
    return_type=DocList[MyDocWithMatches],
    request_size=10
)
for doc in docs:
    print(f'Query {doc.text} has {len(doc.matches)} matches')
```