Hot deployment
Deploying services by saving a file in your project - no restarts and no manual steps.
Hot deployment means that saving a Python file in your project deploys it to a running Zato environment within a couple of seconds, with no restarts and no manual steps. The same mechanism also picks up configuration files, rule files and enmasse definitions.
Your services live in a project directory on your host or in your git repository, the directory is mounted into the Zato container, and the platform watches it for changes. You never copy files into the container and you never edit anything inside it - the project on the host is the single source of truth, as described in the deployment tutorial.
A complete scenario
Everything below runs as is - a new project, one service and the container that deploys it.
Create the project directory on your host:
Save this as ~/myproject/impl/src/api/hello.py:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
# ##############################################################################
class HelloService(Service):
""" Replies with a greeting.
"""
name = 'api.hello'
def handle(self):
self.logger.info(f'cid:{self.cid} Received a new request')
self.response.payload.message = 'Hello from a hot-deployed service'
# ##############################################################################
Start a container with the project mounted and pointed at through Zato_Project_Root:
docker run --pull=always -it --rm -p 22022:22 -p 8183:8183 -p 11223:11223 -p 17010:17010 \
--name zato-4.1 -e Zato_Password=mypassword \
-e Zato_Project_Root=/opt/hot-deploy/myproject \
-v ~/myproject:/opt/hot-deploy/myproject:ro \
zatosource/zato-4.1
Once the environment is up, the server log confirms the deployment:
Invoke the service from the Dashboard at http://localhost:8183 under Services -> IDE - select api.hello, click Invoke and the response is:
Now change the greeting in hello.py on your host and save the file. A moment later the log reports the same deployment line again - invoke the service once more and the new text is in the response. That is the whole workflow: save, wait a second, invoke.
The rest of this page is the reference behind the scenario - the layout rules, the deployment order and what else is watched besides Python files.
The project layout
A project follows the layout of the project blueprint:
myproject
├── config
│ ├── enmasse
│ │ └── enmasse.yaml
│ ├── python-reqs
│ │ └── requirements.txt
│ └── user-conf
│ └── myconf.ini
└── impl
└── src
└── api
├── billing.py
└── employee.py
Two rules make a directory deployable:
- Code must be under a directory named
src - Directories under
srcmust start with one of these prefixes:api,common,util,model,core,channel,adapter,services
Nested directories are allowed and nested packages need an __init__.py file.
How the platform finds your project
The Zato_Project_Root environment variable points to the project directory. With the blueprint, the provisioning script writes it to config/auto-generated/env.ini and the container reads it from there - you do not set it by hand.
More than one project can be deployed at a time - each additional one uses its own variable with any suffix, e.g. Zato_Project_Root_Billing, and all of them accept multiple colon-separated paths.
Deployment order
Directories deploy in a fixed order of their prefixes:
Shared code deploys first, which is why modules with models and utilities belong under common, util or model, while the services that use them belong under api or services.
Imports between deployed files
The src directory of each project becomes an import root. A module imports another one by its path relative to src:
# In impl/src/api/billing.py, importing from impl/src/common/models.py
from common.models import Customer
When a shared module changes, every service that imports it is redeployed automatically - saving common/models.py also redeploys api/billing.py if it imports from that module.
What is watched and when it deploys
The platform watches the project recursively, subdirectories included, for these file types:
*.py- services and shared modules*.ini- configuration files, reloaded in RAM with no restart*.zrules- rule engine rulesenmasse*.yamlandenmasse*.yml- enmasse definitions, imported on change
A file deploys after it has been saved and its size has settled, which in practice means a second or two after you save it in your editor. Compiled artifacts and directories such as __pycache__ or .git are ignored.
Deployed services can receive REST channels created automatically, based on patterns of service names.
Deploying from the Dashboard
The Dashboard offers two ways to deploy a service without touching the file system:
- The service list has an upload area where a
.pyfile can be dropped - The built-in IDE edits and deploys services directly in the browser
Both are convenient for experimentation, but anything created this way lives only inside the container and disappears when the container stops. Work that needs to survive belongs in the project directory in git - the deployment tutorial covers the workflow.