Managing Canisters
If you have experimented with using the SDK by following the tutorials in this section or by cloning examples from the examples repository, you are already familiar with how to build and deploy programs as canisters. This section provides additional information about the canister lifecycle and how to manage canisters.
Obtaining a Canister Identifier
Depending on your preferred development workflow, you can obtain a unique identifier for your canister, before or after you have a program ready to compile. For example, if you want to reserve a unique identifier for your canister on a subnet before you have written any code, you can do so by running the dfx canister create
command. This command essentially creates an empty canister placeholder into which you can later install your code. The resulting canister will obtain a unique identifier.
To obtain a unique identifier for a canister:
Open a new terminal window or tab on your computer.
Create a new project for the canister you plan to create by running a command similar to the following:
`dfx new YOUR-PROJECT-NAME`
Note that the name you use for the project is also used as the canister name by default.
Change to your new project directory.
Open the
dfx.json
configuration file and set the host and port for the canister execution environment you want to use (e.g. the IC blockchain).If you are using a local deployment, you can skip this step.
You can also optionally change the names of your canisters or add canister settings to the configuration file if you want to create identifiers for any additional canisters you think you will need before compiling code.
Start the local canister execution environment, if necessary, by running the following command:
dfx start --background
In most cases, this step is only necessary if you are running the canisters locally.
If you were registering canisters to run on a remote execution environment, e.g. the IC blockchain, you would include the
--network
command-line option to perform tasks on the environment specified under this parameter.Register unique identifiers for the canisters defined in the
dfx.json
by running the following command:dfx canister create --all
The command creates the
.dfx/local
directory and adds thecanister_ids.json
file to that directory for the project.
Build a Canister with a Local Identifier
After you have written source code for your project, you need to compile it into a WebAssembly module before deploying it as a canister.
If you are only compiling your project for local debugging, you can generate a locally-defined identifier for your project.
To generate a locally-defined identifier:
Create a project with the configuration settings and program logic to suit your needs.
Start the local canister execution environment, if necessary.
If you were compiling canisters to run on a remote execution environment, e.g. the IC blockchain, you would include the
--network
command-line option to perform tasks on the environment specified under this parameter.Generate hard-coded local identifiers for the canisters defined in the
dfx.json
by running the following command:dfx build --check
Note that you must register unique canister identifiers to replace your locally-defined identifier before you can deploy the project on the IC blockchain.
Deploy Canisters
After you have compiled a program, you can install the compiled code in a canister running either on a local canister execution environment or on the IC blockchain.
The canister identifier that was created in advance or during the build process determines where your code is installed during deployment.
To deploy the code for the first time:
Open a new terminal and navigate to your project directory.
Start the local canister execution environment, if necessary.
In most cases, this step is only necessary if you are running the canisters locally.
If you were registering canisters to run on a remote execution environment, e.g. the IC blockchain, you would include the
--network
command-line option to perform tasks on the environment specified under this parameter.Verify you have canister identifiers for all of the canisters you want to deploy.
Deploy all of the canisters by running the following command:
dfx canister install --all
Look up a Canister ID
All canisters have unique identifiers. You often need to use these identifiers to interact with the canister. For example, if you want to access the frontend canister for a dapp or interact with a service using the Candid web interface, you must specify the appropriate canister identifier.
Because the identifiers are specific to the environment where the canisters are deployed, the files used to store the information are in different directories. For example, identifiers for a canister deployed locally are located in the project’s .dfx/local/canister_ids.json
file.
You can look up the canister identifier for any specific canister by running the dfx canister id
command. For example, to look up the the canister identifier for the lookup
canister deployed on the local canister execution environment, you could run the following command:
dfx canister id lookup
To look up the canister identifier for the same canister deployed on the environment specified by the ic
alias, you would run the following command:
dfx canister --network=ic id lookup
Add a Wallet for Existing Canisters
When you are doing local development, creating a new project automatically creates a default wallet for you to use with the canisters in that project. If you want to add a wallet for projects with canisters that you have previously created, you can force dfx
to generate one by taking a couple of manual steps.
To add a wallet for use with an existing canister:
Open a terminal and navigate to your project directory.
Stop the local canister execution environment, if necessary, by running the following command:
dfx stop
Delete the
.dfx
directory.Start the local canister execution environment network by running the following command:
dfx start --clean
Reinstall a Canister
During the development cycle, you might want to install, then replace your program as you debug and improve it.
In this scenario, you might want to keep the canister identifier you have registered but without preserving any of the canister code or state. For example, your canister might only have test data that you don’t want to keep or you might have decided to change the program altogether but want to reinstall under a canister identifier you used to install a previous program.
To reinstall a canister:
Open a new terminal and navigate to your project directory.
Start the local canister execution environment, if necessary.
In most cases, this step is only necessary if you are running the canisters locally.
If you were registering canisters to run on a remote execution environment, e.g. the IC blockchain, you would include the
--network
command-line option to perform tasks on the environment specified under this parameter.Verify you have canister identifiers for all of the canisters you want to re-deploy.
Re-deploy all of the canisters by running the following command for every canister:
dfx canister install <canister id or name> --mode reinstall
Note that you can use the reinstall
mode to replace any canister, regardless of whether the canister has code or state associated with it.
Set an Identity to own a Canister
In most cases, a default
user identity is created for you automatically the first time you run the dfx canister create
command. This default identity consists of the public and private key pair generated for your local user account. Typically, this default
identity is also the default owner of all of the projects you create and all of the canisters you deploy. You can, however, proactively create and use identities of your choice to circumvent the default
user identity from being used.
As an example, the following scenario illustrates creating a registered_owner
identity that is then used to register, build, deploy, and call the pubs
project.
To set an identity for a project:
Create a new project by running the following command:
dfx new pubs
Change to the project directory by running the following command:
cd pubs
Start the local canister execution environment in the background by running the following command:
dfx start --background
Create a new
registered_owner
identity by running the following command:dfx identity new registered_owner
Set the active user context to use the
registered_owner
identity by running the following command:dfx identity use registered_owner
Register, build, and deploy canisters for the project by running the following commands:
dfx canister create --all
dfx build --all
dfx canister install --allThese commands run using the
registered_owner
identity, making that user the owner of the canisters deployed.Call the
greet
function to verify a successful deployment by running the following command:dfx canister call pubs greet '("Sam")'
Managing the Running State of a Canister
After you deploy a canister, it can begin receiving and processing requests from users and from other canisters. Canisters that are available to send requests and receive replies are considered in be in a Running state.
Although canisters are normally placed in the Running state by default, there are cases where you might want to temporarily or permanently stop a canister. For example, you might want to stop a canister before upgrading it. Stopping a canister helps to ensure proper handling of any messages that are in progress and need to either run to completion or be rolled back. You might also want to stop a canister to clear its message queue cleanly as a prerequisite to deleting the canister.
You can check the current status of all canisters or a specified canister by running the dfx canister status
command. For example, to see the status for all canisters running on the local canister execution environment, you would run the following command:
dfx canister status --all
This command returns output similar to the following if canisters are currently running:
Canister status_check's status is Running.
Canister status_check_assets's status is Running.
You can stop canisters that are currently running by running the dfx canister stop
command.
dfx canister stop --all
This command displays output similar to the following:
Stopping code for canister status_check, with canister_id 75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
Stopping code for canister status_check_assets, with canister_id cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
If you were to rerun the dfx canister status
command, you might see a status of Stopped
indicating that there were no pending messages that needed to processed or a status of Stopping
indicating that there were messages in-flight that needed to be addressed.
To restart a canister-for example, after a successful canister upgrade—you can run the dfx canister start
command. For example, to restart all of the canisters, you would run the following command:
dfx canister start --all
This command displays output similar to the following:
Starting code for canister status_check, with canister_id 75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
Starting code for canister status_check_assets, with canister_id cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
Upgrade a Canister
Unlike a canister reinstall that preserves the canister identifier but no state, a canister upgrade enables you to preserve the state of a deployed canister, and change the code.
For example, assume you have a dapp that manages professional profiles and social connections. If you want to add a new feature to the dapp, you need to be able to update the canister code without losing any of the previously-stored data. A canister upgrade enables you to update existing canister identifiers with program changes without losing the program state.
To preserve state when you are upgrading a canister written in Motoko, be sure to use the stable
keyword to identify the variables you want to preserve. For more information about preserving variable state in Motoko, see Stable variables and upgrade methods. If you are upgrading a canister written in Rust, you should use pre_upgrade
and post_upgrade
functions as illustrated in the Rust CDK asset storage example to ensure data is properly preserved after a canister upgrade.
To upgrade a canister:
Open a new terminal and navigate to your project directory.
Start the local canister execution environment, if necessary.
In most cases, this step is only necessary if you are running the canisters locally.
If you were registering canisters to run on a remote execution environment, e.g. the IC blockchain, you would include the
--network
command-line option to perform tasks on the environment specified under this parameter.Verify you have canister identifiers for all of the canisters you want to upgrade.
Note that your program must identify the variables for which to maintain state by using the
stable
keyword in the variable declaration.For more information about declaring stable variables, see the Motoko Programming Language Guide.
Upgrade all of the canisters by running the following command:
dfx canister install --all --mode upgrade
Delete a Canister
If you want to permanently delete a specific canister or all canisters for a specific project on a given deployment (either local, or remote), you can do so by running the dfx canister delete
command.
Deleting a canister removes the canister identifier, code, and state. Before you can delete a canister, however, you must first stop the canister to clear any pending message requests or replies.
To delete all canisters for a project:
Open a new terminal and navigate to your project directory.
Start the local canister execution environment, if necessary.
In most cases, this step is only necessary if you are running the canisters locally.
If you were deleting canisters to run on a remote execution environment, e.g. the IC blockchain, you would include the
--network
command-line option to perform tasks on the environment specified under this parameter.Check the status of the project canisters running on the local canister execution environment by running the following command:
dfx canister status --all
Stop all of the project canisters by running the following command:
dfx canister stop --all
Delete all of the project canisters by running the following command:
dfx canister delete --all