Deploy with Docker Compose#
One of the simplest ways of either prototyping or serving in
production is to run your Flow
with docker-compose
.
A Flow
is composed of Executor
s which run Python code
defined to operate on DocumentArray
. These Executors
will live in different runtimes depending on how you want to deploy
your Flow.
By default, if you are serving your Flow locally they will live within processes. Nevertheless, because Jina 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 with one line:
from jina import Flow
flow = Flow(...).add(...).add(...)
flow.to_docker_compose_yaml('docker-compose.yml')
Jina will generate a docker-compose.yml
configuration file that you can use directly with
docker-compose
and corresponds to your Flow
, avoiding the overhead of manually defining all the services needed for the Flow
.
Caution
All Executors in the Flow should be used with jinahub+docker://...
or docker://...
.
Caution
If you are using Executor which rely on docker image built with a jina version prior to 3.1.3, please remove the
health check from the dump yaml file as they are only compatible with 3.1.3+ otherwise your docker compose services will
always be unhealthy
Example: Indexing and searching images using CLIPEncoder and ANNLiteIndexer#
To follow this how-to, you should first ensure that Docker Compose
is installed locally.
This example shows how to build and deploy a Flow with Docker Compose, using CLIPImageEncoder
as an image encoder and ANNLiteIndexer
as an indexer to perform fast nearest
neighbor retrieval on image embeddings.
Deploy your Flow#
First let’s define the Flow and generate the Docker Compose YAML configuration from it
In a flow.yml
file :
jtype: Flow
with:
port: 8080
protocol: http
executors:
- name: encoder
uses: jinahub+docker://CLIPEncoder
replicas: 2
- name: indexer
uses: jinahub+docker://AnnLiteIndexer
uses_with:
dim: 512
shards: 2
then in a shell do:
jina export docker-compose flow.yml docker-compose.yml
In python run
from jina import Flow
flow = (
Flow(port=8080, protocol='http')
.add(name='encoder', uses='jinahub+docker://CLIPEncoder', replicas=2)
.add(
name='indexer',
uses='jinahub+docker://AnnLiteIndexer',
uses_with={'dim': 512},
shards=2,
)
)
flow.to_docker_compose_yaml('docker-compose.yml')
Hint
You can use a custom jina Docker image for the Gateway service. Just set the envrironment variable JINA_GATEWAY_IMAGE
to the desired image before generating the configuration.
let’s take a look at the generated compose file:
version: '3.3'
...
services:
encoder-rep-0: # # # # # # # # # # #
# Encoder #
encoder-rep-1: # # # # # # # # # # #
indexer-head: # # # # # # # # # # #
# #
indexer-0: # Indexer #
# #
indexer-1: # # # # # # # # # # #
gateway:
...
ports:
- 8080:8080
Tip
The default compose file generated by the Flow contains no special configuration or settings. You may want to adapt it to your own needs.
Here you can see that 5 services will be 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 :
docker-compose -f docker-compose.yml up
Query your Flow#
Once we see that all the services in the Flow are ready, we can start sending index and search requests.
First let’s define a client:
from jina.clients import Client
client = Client(host='http://localhost:8080')
Then let’s index the set of images we want to search:
from docarray import DocumentArray
da = DocumentArray.pull('demo-da-images-jina', show_progress=True)
da_query = da[0:1] # one document for query
da_index = da[1:] # the rest is for indexing
indexed_docs = client.index(inputs=da_index)
print(f'Indexed Documents: {len(indexed_docs)}')
Indexed Documents: 99
We indexer 99 Documents !
Then let’s search for the closest image to our query image:
queried_docs = client.search(inputs=da_query)
matches = queried_docs[0].matches
print(f'Matched Documents: {len(matches)}')
Matched Documents: 10
Now have the list of the 10 closest image to the query !