Build your first iApp
In this section we will show you how you can create an iApp (iExec confidential application) over the iExec infrastructure.
Prerequisites
- Docker 17.05 or higher on the daemon and client.
- Dockerhub account.
- iExec SDK 8.0.0 or higher.
- Quickstart tutorial completed
In this guide, we will prepare an iExec iApp based on an existing docker image and we will run it on iExec decentralized infrastructure.
Understand what is an iExec decentralized application (iApp)?
iExec leverage Docker containers to ensure the execution of your application on a decentralized infrastructure. iExec supports Linux-based docker images.
Why using Docker containers?
- Docker Engine is the most widely used container engine.
- A Docker container image is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. This allows for computations to be run on any worker connected to the decentralized infrastructure.
- Docker also enables the creation of new layers on top of existing images. This allows for any iExec apps to be easily built on top of existing docker images.
What kind of application can I build on iExec?
Today you can run any application as a task. This means services are not supported for now.
Build your iApp
Create the folder tree for your application in ~/iexec-projects/
.
cd ~/iexec-projects
mkdir hello-world-iapp
cd hello-world-iapp
mkdir src
touch Dockerfile
Write the iApp
WARNING
For demo purposes, we omitted some development best practices in these examples.
Make sure to check your field's best practices before going to production.
The following examples only feature Javascript and Python use cases for simplicity concerns but remember that you can run on iExec anything which is Dockerizable.
Copy the following content in src/
.
const fsPromises = require('fs').promises;
(async () => {
try {
const iexecOut = process.env.IEXEC_OUT;
// Do whatever you want (let's write hello world here)
const message = process.argv.length > 2 ? process.argv[2] : 'World';
const text = `Hello, ${message}!`;
console.log(text);
// Append some results in /iexec_out/
await fsPromises.writeFile(`${iexecOut}/result.txt`, text);
// Declare everything is computed
const computedJsonObj = {
'deterministic-output-path': `${iexecOut}/result.txt`,
};
await fsPromises.writeFile(
`${iexecOut}/computed.json`,
JSON.stringify(computedJsonObj)
);
} catch (e) {
console.log(e);
process.exit(1);
}
})();
import os
import sys
import json
iexec_out = os.environ['IEXEC_OUT']
# Do whatever you want (let's write hello world here)
text = 'Hello, {}!'.format(sys.argv[1] if len(sys.argv) > 1 else "World")
print(text)
# Append some results in /iexec_out/
with open(iexec_out + '/result.txt', 'w+') as fout:
fout.write(text)
# Declare everything is computed
with open(iexec_out + '/computed.json', 'w+') as f:
json.dump({ "deterministic-output-path" : iexec_out + '/result.txt' }, f)
WARNING
As a developer, make it a rule to never log sensitive information in your application. Execution logs are accessible by:
- worker(s) involved in the task
- the workerpool manager
- the requester of the task
Dockerize your iApp
Copy the following content in Dockerfile
.
FROM node:22-alpine3.21
### install your dependencies if you have some
RUN mkdir /app && cd /app
COPY ./src /app
ENTRYPOINT [ "node", "/app/app.js"]
FROM python:3.13.3-alpine3.21
### install python dependencies if you have some
COPY ./src /app
ENTRYPOINT ["python3", "/app/app.py"]
Build the docker image.
WARNING
iExec expects your Docker container to be built for the linux/amd64
platform. However, if you develop on a Mac with Apple M processor, the platform is linux/arm64
, which is different. To prepare your application, you will need to install buildkit
and then prepare your docker image for both platforms.
brew install buildkit
# ARM64 variant for local testing only
docker buildx build --platform linux/arm64 --tag <docker-hub-user>/hello-world .
# AMD64 variant to deploy on iExec
docker buildx build --platform linux/amd64 --tag <docker-hub-user>/hello-world .
docker build --tag hello-world .
TIP
docker build
produce an image id, using --tag <name>
option is a convenient way to name the image to reuse it in the next steps.
Congratulations you built your first docker image for iExec!
Test your iApp locally
Basic test
Create local volumes to simulate input and output directories.
mkdir -p ./tmp/iexec_in
mkdir -p ./tmp/iexec_out
Run your application locally (container volumes bound with local volumes).
docker run --rm \
-v ./tmp/iexec_in:/iexec_in \
-v ./tmp/iexec_out:/iexec_out \
-e IEXEC_IN=/iexec_in \
-e IEXEC_OUT=/iexec_out \
hello-world arg1 arg2 arg3
Docker run [options] image [args]
docker run usage:
docker run [OPTIONS] IMAGE [COMMAND] [ARGS...]
Use [COMMAND]
and [ARGS...]
to simulate the requester arguments
useful options for iExec:
-v
: Bind mount a volume. Use it to bind input and output directories (/iexec_in
and /iexec_out
)
-e
: Set environnement variable. Use it to simulate iExec Runtime variables
Test with input files
Starting with the basic test you can simulate input files.
For each input file:
- Copy it in the local volume bound to
/iexec_in
. - Add
-e IEXEC_INPUT_FILE_NAME_x=NAME
to docker run options (x
is the index of the file starting by 1 andNAME
is the name of the file)
Add -e IEXEC_INPUT_FILES_NUMBER=n
to docker run options (n
is the total number of input files).
Example with two inputs files:
touch ./tmp/iexec_in/file1 && \
touch ./tmp/iexec_in/file2 && \
docker run \
-v ./tmp/iexec_in:/iexec_in \
-v ./tmp/iexec_out:/iexec_out \
-e IEXEC_IN=/iexec_in \
-e IEXEC_OUT=/iexec_out \
-e IEXEC_INPUT_FILE_NAME_1=file1 \
-e IEXEC_INPUT_FILE_NAME_2=file2 \
-e IEXEC_INPUT_FILES_NUMBER=2 \
hello-world \
arg1 arg2 arg3
Test your iApp on iExec
Push your iApp to Dockerhub
Login to your Dockerhub account.
docker login
Tag your application image to push it to your dockerhub public repository.
docker tag hello-world <docker-hub-user>/hello-world:1.0.0
WARNING
replace <docker-hub-user>
with your docker user name
Push the image to Dockerhub.
docker push <docker-hub-user>/hello-world:1.0.0
Congratulations, your iApp is ready to be deployed on iExec!
Deploy your iApp on iExec
You already learned how to deploy the default iApp on iExec in the previous tutorial.
Go back to the iexec-project
folder.
cd ~/iexec-projects/
You will need a few configurations in iexec.json
to deploy your iApp:
- Replace iApp name with your application name (display only)
- Replace iApp multiaddr with your iApp image download URI (should looks like
docker.io/<docker-hub-user>/hello-world:1.0.0
) - Replace iApp checksum with your application image checksum (see tip below)
INFO
The checksum of your iApp is the sha256 digest of the docker image prefixed with 0x
, you can use the following command to get it.
docker pull <docker-hub-user>/hello-world:1.0.0 | grep "Digest: sha256:" | sed 's/.*sha256:/0x/'
Deploy your iApp on iExec
iexec app deploy --chain arbitrum-mainnet
Verify the deployed iApp (name, multiaddr, checksum, owner)
iexec app show --chain arbitrum-mainnet
Run your iApp on iExec
iexec app run --chain arbitrum-mainnet --workerpool 0x2C06263943180Cc024dAFfeEe15612DB6e5fD248 --watch
INFO
Using arguments:
You can pass arguments to the iApp using --args <args>
option.
With --args "dostuff --with-option"
the iApp will receive ["dostuff", "--with-option"]
as process args.
Using input files:
You can pass input files to the iApp using --input-files <list of URL>
option.
With --input-files https://example.com/file-A.txt,https://example.com/file-B.zip
the iExec worker will download the files before running the iApp in IEXEC_IN
, and let the iApp access them through variables:
file-A.txt
asIEXEC_INPUT_FILE_NAME_1
file-B.zip
asIEXEC_INPUT_FILE_NAME_2
Once the run is completed copy the taskid from iexec app run
output to download and check the result
iexec task show --chain arbitrum-mainnet <taskid> --download my-app-result \
&& unzip my-app-result.zip -d my-app-result
Congratulations your iApp successfully ran on iExec!
Manage your iApp's output
iExec enables running apps producing output files, you will need a place for storing your apps outputs.
INFO
iExec provides a default storage solution based on IPFS. This solution ensures your result to be publicly accessible through a decentralized network.
To ensure your business data remains secure and private, iExec offers optional RSA result encryption and the ability to push results to private storage providers. For more information, refer to iexec storage --help
and theiExec SDK.
Access to iApp and task logs on iExec
Sometimes things don't work out right the first time and you may need to Debug your tasks.
Publish your iApp on the iExec marketplace
iexec app publish --chain arbitrum-mainnet
Congratulations your application is now available on iExec!
What's next?
In this tutorial you learned about the key concepts for building an iApp on iExec:
- iExec iApp inputs and outputs
- iExec iApp must produce a
computed.json
file (required for the proof of execution) - using docker to package your iApp with all its dependencies
- testing an iExec iApp locally
- publishing on dockerhub