Skip to content

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

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/.

bash
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/ .

javascript
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);
  }
})();
python
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 .

bash
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"]
bash
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.

bash
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 .
bash
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.

bash
mkdir -p ./tmp/iexec_in
mkdir -p ./tmp/iexec_out

Run your application locally (container volumes bound with local volumes).

bash
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 and NAME 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:

bash
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.

bash
docker login

Tag your application image to push it to your dockerhub public repository.

bash
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.

bash
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.

bash
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.

bash
docker pull <docker-hub-user>/hello-world:1.0.0 | grep "Digest: sha256:" | sed 's/.*sha256:/0x/'

Deploy your iApp on iExec

bash
iexec app deploy --chain arbitrum-mainnet

Verify the deployed iApp (name, multiaddr, checksum, owner)

bash
iexec app show --chain arbitrum-mainnet

Run your iApp on iExec

bash
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

bash
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

bash
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