Working with tasks
Architect components have the concept of a Task, similar to a cron job. Since Tasks are defined in a component in a similar way to Services, you can configure your Tasks with dependencies on other components, take secrets, or call a service defined in the same component.
This guide will walk through the process of creating a new component with a Task that exercises most of the features available to Tasks.
- Create an example container and script to run as a Task
- Defining a minimal Component with a Task, and execute it locally
- Updating the Component to improve local development experience
- Tasks with Secrets
- Tasks with Dependencies
Create a Script and Dockerfile for our Task
Before getting started with the components, create a script for your task, and a dockerfile so you can bake the script into an image.
The Dockerfile
:
The my-task.sh
:
With those created, go ahead and build the docker image and execute it, just to verify it’s working as expected.
You can see that when the task runs without the GREETING
environment variable,
it displayed the typical “Hello, world!”, but will provide a more customized
message when the GREETING
variable is provided. With the docker image working,
proceed with creating the Architect Component and Task.
Define a Minimal Component Task
In your my-task
directory, create an architect file to define your component:
Now you can create a Task in the component file just as you would a Service. In this case you’ll give the component a brief description, a blank schedule so it runs only when manually executed, and finally you provide the build context as the local directly. The Component Task docs cover all the nuances in the task definition, as do the Task Reference docs.
The architect.yml
:
You can validate the component to verify aren’t any mistakes:
To run this locally, you’ll need to link the component by running:
Now that the component is linked, you can deploy it locally using the
architect dev
command. Under the hood, this creates a docker-compose file
which will be used as the task is executed.
And now you can execute the task locally:
And there you have it; you’ve executed your task locally! But you may want to improve the component definition to reduce friction during development.
Local Task Development
Development generally requires rapid iteration, and needing to run dev
and
task:exec
each time you want to test can be a tedious experience. To alleviate
this, you can make use of the debug
feature to mount our source code when you
run the task without having to re-deploy. This can be achieved by updating the
component with a debug block, re-deploying (just the once) to update the
component configuration. You will only use a few of the available local
development features, but more info can be found in the
Local Configuration docs.
Now you can update the architect file with the debug block containing a volume mount that overrides the script in the container with the script from the local filesystem:
You will have to redeploy the component because you changed its definition, so go ahead and redeploy and execute it again to make sure everything is still working as expected.
Excellent! With this version of your component, the my-task.sh
script is being
mounted into the container and used when the task is executed. You should make a
change to the script and re-execute the task to verify this:
Change the my-task.sh
file to include a waving emoji in the output:
Now you’ll see the emoji in the output when you execute the task again without re-registering or re-deploying the component:
Tasks with Secrets
The task you created supports a GREETING
environment variable, so you can make
use of that as you deploy the component by setting a value as a secret. In
addition to adding the secrets
section to the component, you’ll also need to
declare the GREETING
environment variable on the task, and assign it to the
value given by the secret. More information about secrets can be found in the
Components Secrets docs and the
Secrets Reference docs.
The architect.yml
file:
Now you can redeploy the component with a secret value, whose value will be used
when the task is executed. It’s important to understand that these secrets are
set at deploy time, so you cannot re-declare the GREETING
value later when you
execute the task.
Tasks with Dependencies
As mentioned earlier, tasks can use the same facilities as services which also means a Task can depend on a Service, just as Services can depend on other Services. So you can expand the component to include a service for generating names to use in your task’s greeting.
To start, add a really simple node server in a file called server.js
, and make
a dedicated docker image.
The server/server.js
:
The server/Dockerfile
:
The server will respond with just the name in the body, so you can update the
script to simply curl the server address provided by the API_URL
variable.
Now go ahead and add the service to the architect file, and then pass the URL for the service into the task using the environment variable referenced in the script:
Great! Now you can deploy your changes.
And now when you execute the task again, you’ll see a greeting for a random name provided by the dependent service: