DEV Community

Aditya
Aditya

Posted on • Originally published at aditya26sg.substack.com on

How I worked with Docker profiles?

I was working on a script that is supposed to be executed on Ethereum mainnet and do some operations like Deposit some tokens in a Defi vault and then withdraw them too, get some on-chain data and show it works successfully.

Now I wanted it to work for other people too who just take a pull from my repo and try to run this script. So naturally I used Docker to make it easier for anyone to do this.

Now doing some write operations on Ethereum mainnet costs real money, which I only have some. So you can create a fork of the actual network and start a local node to simulate the real network and have the script perform write operations on the fork.

The fork doesn’t costs you real money, and you can do a lot of stuff there. But in brief it allows you to simulate transactions in a way that the real network would without costing real money.

So naturally I wanted all this to happen using a single command and different execution profiles. So the script’s code remains the same, but I would like to execute it in a fork mode, then on mainnet mode whenever I want.

To work with the fork mode I first started with 2 terminal sessions where one executes the script commands and other runs the forked network node. So this is a 2 step process normally. But with docker profiles I was able to do this in a single command.

Here is where Docker profile was really helpful as it allowed me to switch between environments in which the script should execute, mainnet or fork.

Docker profiles execution flow

Here is the docker-compose.yml which shows how I used profiles

services:
  anvil:
    build:
      context: .
      dockerfile: Dockerfile.anvil
    container_name: lombard-anvil
    command:
      - --host
      - "0.0.0.0"
      - --port
      - "8545"
      - --fork-url
      - ${RPC_URL}
      - --silent
    ports:
      - "8545:8545"
    healthcheck:
      test:
        - CMD
        - cast
        - block-number
        - --rpc-url
        - http://127.0.0.1:8545
      interval: 3s
      timeout: 3s
      retries: 10
      start_period: 5s
    profiles:
      - fork

  # fork mode
  app-fork:
    build: .
    container_name: lombard-app-fork
    env_file:
      - .env
    environment:
      - RPC_URL=http://anvil:8545
      - PRIVATE_KEY=${PRIVATE_KEY}
    depends_on:
      anvil:
        condition: service_healthy
    command: ["${TOKEN_ADDRESS}", "${TOKEN_AMOUNT}"]
    profiles:
      - fork

  # mainnet mode
  app-mainnet:
    build: .
    container_name: lombard-app-mainnet
    env_file:
      - .env
    environment:
      - RPC_URL=${RPC_URL}
      - PRIVATE_KEY=${PRIVATE_KEY}
    command: ["${TOKEN_ADDRESS}", "${TOKEN_AMOUNT}"]
    profiles:
      - mainnet
Enter fullscreen mode Exit fullscreen mode

So this compose has 3 services anvil, app-fork and app-mainnet.

Anvil is the service that forks the Ethereum mainnet latest state and runs a local blockchain node. This is perfect for doing the scripts simulation where I don’t want to spend real money.

The app-fork service initializes the requirements to run the script and makes sure that anvil fork is up and running first before executing the script. It also overwrites the environment variable RPC_URL to use anvil’s rpc and not the mainnet one so the transactions goes to the anvil node and not the real ethereum node.

Lastly the app-mainnet simply runs the script in mainnet mode, it doesn’t need an anvil local node running as it has the live RPC_URL from the .env to send transactions to the Ethereum network. This costs real money.

With this compose and using commands like below I am able to switch between environments easily in which I want to execute my script.

To execute in fork mode:

docker compose --profile fork up --build --abort-on-container-exit --exit-code-from app-fork
Enter fullscreen mode Exit fullscreen mode

To execute in mainnet mode:

docker compose --profile mainnet up --build
Enter fullscreen mode Exit fullscreen mode

Here is the link to the repo of the script I was talking about: https://github.com/aditya172926/lombard-vault-challenge

Hope this gives you a better idea about working with Docker profiles.

Top comments (0)