Skip to main content

Local deployment

Beginner
Getting started
Tutorial

Overview

When developing canisters and projects, it is recommended to first deploy your project to the local development environment. This is so you can fabricate cycles in your local development environment, which you cannot do on the mainnet. Cycles are charged for the resources used by your canister. Learn more about cycles.

Deploying to your local development environment is similar to deploying to a testnet. ICP does not have a testnet available for developers to deploy to. Instead, the IC SDK runs a local version of the ICP node software known as the replica and provides a single-node environment on your local machine for you to deploy canisters to.

Prerequisites

Before you create your first canister, verify the following:

  •   [x] You have an internet connection and access to a shell terminal on your local computer.

  •   [x] You have Node.js installed if you want to include the default template files for frontend development in your project.

  •   [x] You have downloaded and installed the IC SDK package as described in the installing the IC SDK page.

Start the local deployment

Before you can build your first project, you need to connect to the local replica. As a best practice, this step requires you to have two terminal shells open, so that you can start and see canister execution operations in one terminal and manage your project in another.

To prepare the local replica:

  • Step 1:  Open a new second terminal window or tab on your local computer.

  • Step 2:  Navigate to the root directory for your project, if necessary.

You should now have two terminals open with your project directory as your current working directory in both terminals.

  • Step 3:  Start the local replica on your computer in your second terminal by running the following command:

dfx start

Depending on your platform and local security settings, you might see a warning displayed. If you are prompted to allow or deny incoming network connections, click Allow.

  • Step 4:  Leave the terminal window that displays canister execution operations open and switch your focus to the first terminal window where you created your new project.

You should perform the remaining steps in the terminal that doesn’t display canister execution operations.

Register, build, and deploy the application

After you connect to the local canister execution environment, you can register, build, and deploy your dapp locally.

To deploy your first canister locally:

  • Step 1:  Check that you are still in the root directory for your project, if needed.

It is recommended to follow the creating your first canister guide to have a simple 'Hello, world!' canister ready to deploy.

  • Step 2:  Ensure that node modules are available in your project directory, if needed, by running the following command:

npm install

For more information about this step, see ensuring node is available in a project.

  • Step 3:  Register, build, and deploy your first dapp by running the following command:

dfx deploy

The dfx deploy command output displays information about the operations it performs. For example, this step registers two identifiers. One is for the hello_backend main program, and the other is for the hello_frontend frontend user interface and installation information similar to the following:

Creating a wallet canister on the local network.
The wallet canister on the "local" network for user "mainnet" is "rwlgt-iiaaa-aaaaa-aaaaa-cai"
Deploying all canisters.
Creating canisters...
Creating canister hello_backend...
hello_backend canister created with canister id: rrkah-fqaaa-aaaaa-aaaaq-cai
Creating canister hello_frontend...
hello_frontend canister created with canister id: ryjl3-tyaaa-aaaaa-aaaba-cai
Building canisters...
Building frontend...
Installing canisters...
Creating UI canister on the local network.
The UI canister on the "local" network is "r7inp-6aaaa-aaaaa-aaabq-cai"
Installing code for canister hello_backend, with canister ID rrkah-fqaaa-aaaaa-aaaaq-cai
Installing code for canister hello_frontend, with canister ID ryjl3-tyaaa-aaaaa-aaaba-cai
Uploading assets to asset canister...
Starting batch.
Staging contents of new and changed assets:
  /sample-asset.txt 1/1 (24 bytes)
  /logo2.svg 1/1 (15139 bytes)
  /index.js.map 1/1 (681670 bytes)
  /index.js.map (gzip) 1/1 (156940 bytes)
  /favicon.ico 1/1 (15406 bytes)
  /main.css 1/1 (537 bytes)
  /main.css (gzip) 1/1 (297 bytes)
  /index.html 1/1 (690 bytes)
  /index.html (gzip) 1/1 (386 bytes)
  /index.js (gzip) 1/1 (152884 bytes)
  /index.js 1/1 (637230 bytes)
Committing batch.
Deployed canisters.
URLs:
  Frontend canister via browser
    hello_frontend: http://127.0.0.1:4943/?canisterId=ryjl3-tyaaa-aaaaa-aaaba-cai
  Backend canister via Candid interface:
    hello_backend: http://127.0.0.1:4943/?canisterId=r7inp-6aaaa-aaaaa-aaabq-cai&id=rrkah-fqaaa-aaaaa-aaaaq-cai

If you create a project with a different name, however, your canister names will match your project name instead of hello_backend and hello_frontend.

Call the canister from the CLI

Call the hello_backend canister and the predefined greet function by running the following command:

dfx canister call hello_backend greet everyone

Let’s take a closer look at this example command:

  •   The dfx canister call command requires you to specify a canister name and a method or function to call.

  •   hello_backend specifies the name of the canister you want to call.

  •   greet specifies the name of the function you want to call in the hello canister.

  •   everyone is the text data type argument that you want to pass to the greet function.

Remember, however, that if you create a project with a different name, the canister name will match your project name, and you’ll need to modify the command line to match the name you used instead of hello_backend. If you were to choose test as the project name, your backend canister would be called test_backend and the frontend canister test_frontend.

Verify the command displays the return value of the greet function. For example:

("Hello, everyone!")

Call the canister from the browser

It is possible to access the frontend canister directly from the browser. You will need to navigate to the URL that was printed in the output of the dfx deploy command (your URL might differ):

Frontend canister via browser
    hello_frontend: http://127.0.0.1:4943/?canisterId=bd3sg-teaaa-aaaaa-qaaba-cai

This will render a webpage with a form that accepts a string and sends it to the backend canister.

The source code of the webpage is defined in the src/hello_frontend/src/index.{html,js} files.

src/hello_frontend/src/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <title>hello</title>
    <base href="/" />
    <link rel="icon" href="favicon.ico" />
    <link type="text/css" rel="stylesheet" href="main.css" />
  </head>
  <body>
    <main>
      <img src="logo2.svg" alt="DFINITY logo" />
      <br />
      <br />
      <form action="#">
        <label for="name">Enter your name: &nbsp;</label>
        <input id="name" alt="Name" type="text" />
        <button type="submit">Click Me!</button>
      </form>
      <section id="greeting"></section>
    </main>
  </body>
</html>
src/hello_frontend/src/index.js
import { hello_backend } from "../../declarations/hello_backend";

document.querySelector("form").addEventListener("submit", async (e) => {
  e.preventDefault();
  const button = e.target.querySelector("button");

  const name = document.getElementById("name").value.toString();

  button.setAttribute("disabled", true);

  // Interact with foo actor, calling the greet method
  const greeting = await hello_backend.greet(name);

  button.removeAttribute("disabled");

  document.getElementById("greeting").innerText = greeting;

  return false;
});

The JavaScript code running in the browser uses the agent-js library to interact with the backend canister. The library creates a wrapper JavaScript object based on the interface of the canister. That wrapper object provides convenience methods for calling the canister functions as if they were JavaScript functions:

const greeting = await hello_backend.greet(name);

Stop the local canister execution environment

After testing the application in the browser, you can stop the local canister execution environment so that it doesn’t continue running in the background.

To stop the local deployment:

  • Step 1:  In the terminal that displays the development server, press Control-C to interrupt the development server process.

  • Step 2:  In the terminal that displays canister execution operations, press Control-C to interrupt the local network process.

  • Step 3:  Stop the local replica running on your local computer by running the following command:

dfx stop

Next steps

Next, you can deploy your canister on the playground.