Before we start, let's define some vocabulary that will be used in the next step.
On both your Web App and your workers, you will need to:
Traffic is always initiated by the Agent to Zenaton. You must open the following ports for the Agent to work:
443/tcp: port used by the Agent to send requests to Zenaton API
5672/tcp: port used by the Agent to send and receive instructions
Since we don't want any task execution to happen in your Web App, we will start the Agent there in "client mode". Client mode means that the Agent is able to dispatch workflows and tasks, send events, pause, kill and resume workflows, but will not handle any of the executions.
To start the Agent in client mode, just add the
--client option during configuration:
zenaton listen --client --python
On your Workers, configure the Agent as usual:
zenaton listen --boot=boot.py
If you want to use your Web App as a Worker also, and thus avoid having more servers to manage, just configure your Agent in your Web App as if it was a Worker.
When deploying to production, make sure to use the
To make sure your application is able to dispatch tasks and workflows at any time, you need to make sure the Agent is always running and listening using your application credentials.
To enforce this, you will need to use a software capable of monitoring the execution of a process and make sure it's always running.
You can use
supervisord, or any similar
software to achieve this. Let's see how we can do that using
systemd. You will need to run the following commands as user
First, create a systemd unit file:
Make sure the file permissions are correct:
chmod 664 /etc/systemd/system/zenaton-agent.service
Open the file we just created with your favorite text editor and add the following content:
[Unit] Description=Zenaton Agent Daemon service After=network-online.target [Service] Type=forking # User and group that will be used to run your Zenaton Agent. User must have a Zenaton Agent installation # in its home directory and have correct permissions to execute your sources. User=... Group=... # Path to sources of your workflows & tasks. WorkingDirectory=... # Add your exact listen command ExecStartPost=/usr/local/bin/zenaton listen --boot=... ExecStart=/usr/local/bin/zenaton start ExecStop=/usr/local/bin/zenaton stop Restart=always [Install] WantedBy=multi-user.target
Make sure to replace
... with correct values.
Docker best practices recommend having only one running process in a container. This is what we are going to achieve. We will need to write a
instructions to build a fully functional Zenaton Agent container.
In our container, we will need:
We will install everything in our container, and start the Zenaton Agent when the container is started.
# Use python as a base image FROM python:3.5 # copy your files into the container COPY src/ start_agent.sh /app/ # make start_agent.sh executable RUN ["chmod", "+x", "/app/start_agent.sh"] # Change the working directory to the one we just created WORKDIR /app # Install Zenaton RUN curl https://install.zenaton.com | sh # Install dependencies RUN pip install -r /app/requirements.txt # Set the PORT environment variable to be used by the Agent ENV PORT 4001 # Document the fact that the container will expose port 4001 EXPOSE 4001 # Set entrypoint to the agent start script ENTRYPOINT ["./start_agent.sh"]
And the content of the
start_agent.sh script, which will start the Agent, run the listen command, and tail the zenaton.out file to make sure the container
#!/bin/sh set -e # Start zenaton worker zenaton start zenaton listen --boot=boot.py # Print zenaton output to stdout touch zenaton.out tail -f zenaton.out
If you want an Agent running in client mode, don't forget to add the
--client option to the listen command in this script.
We can now build the docker image:
docker build --file Dockerfile-agent -t zenaton-agent-python .
The last thing you need to know is that by default, Zenaton libraries assume the Agent is located on the same server as your web application. So it will try
to make HTTP requests to
http://localhost:4001/. When using a separate container for your Agent, you won't have anything responding on this hostname and port.
In your Web App containers, make sure you set the
ZENATON_WORKER_URL environment variable to an ip/hostname and port of the Agent container that must be reachable
from your application container, e.g.
In this example we did not generate a .env file inside the container. So when we run the container, we will need to supply the App ID, Api Token and App Env as environment variables for the Agent to be able to authenticate itself.
docker run --init --rm -e ZENATON_APP_ID=<your app id> -e ZENATON_API_TOKEN=<your api token> -e ZENATON_APP_ENV=production zenaton-agent-python
Alternatively, you could create an
ZENATON_APP_ID=<your app id> ZENATON_API_TOKEN=<your api token> ZENATON_APP_ENV=production
In this case you would run the container like this:
docker run --init --rm --env-file env.list zenaton-agent-python
That's it! Your Agent container is now up and running.
To be able to use Zenaton in your Heroku hosted app, you will need to use our Heroku buildpack. The buildpack will install a Zenaton Agent inside your dynos, allowing your application to dispatch tasks and workflows, send events, etc. You will also be able to use your dynos as Zenaton workers.
To add the buildpack to your project, as well as the required environment variables, use the following commands:
cd <HEROKU_PROJECT_ROOT_FOLDER> # If this is a new Heroku project heroku create # Add the appropriate language-specific buildpack heroku buildpacks:add heroku/python # Add Zenaton buildpack and set your Zenaton credentials heroku buildpacks:add --index 1 zenaton/heroku-buildpack-zenaton heroku config:set ZENATON_APP_ID=<ZENATON_APP_ID> heroku config:set ZENATON_API_TOKEN=<ZENATON_API_TOKEN> heroku config:set ZENATON_APP_ENV=production # ZENATON_LISTEN_ARGS environment variable is used to give the parameters you want to use for the listen command of the Agent heroku config:set ZENATON_LISTEN_ARGS="--boot=boot.py --python" # Deploy to Heroku git push heroku master
<ZENATON_API_TOKEN> with your Zenaton credentials.
When the deploy is finished, the Zenaton Agent will be automatically started when each dyno starts.
The Agent is started in client mode in order to avoid adding load to your web dyno.
If you want to use some dynos to perform the execution of workflows and tasks, you have to make some dynos using type
These dynos will start the Zenaton Agent in regular mode, executing workflows and tasks. In order to make these worker dynos, add them in your
# Procfile web: gunicorn gettingstarted.wsgi --log-file - zenatonworker: tail -f /dev/null
Because the buildpack automatically starts the Zenaton Agent, you do not need to provide any specific command for the dyno, that's why we use
tail -f /dev/null.