Deploying and managing canisters
Once a canister's code has been written, it must be compiled into Wasm, installed into the canister itself, and then deployed to a network. The dfx deploy
command executes each of these tasks as part of the deployment process; however, dfx
commands also exist for running each step individually.
It is recommended to deploy canisters locally or to the temporary playground network to test canister functionality and make adjustments before considering the canister production-ready and deploying it to the mainnet. Deploying canisters locally and to the playground is free and does not cost cycles. Once a canister is deployed to the mainnet, it will consistently consume cycles and will need to be topped up periodically.
Starting the local replica
To deploy your canister locally, first start the local replica. This simulates the mainnet environment with a single node for local development and testing.
dfx start
: Returns replica output in the terminal window. A new terminal window will need to be opened to continue running commands.dfx start --background
: Runs the processes in the background and allows you to continue running commands in the current terminal.
Deploying the project locally
Deploy the backend canister that you have written code for:
dfx deploy PROJECT_NAME_backend --network=local
The --network=local
flag here is redundant and shown for educational purposes. The local network is the default setting for dfx
commands; therefore, no flag is needed to target it.
This will deploy your project to the local replica. In the background, this command:
Creates the canister(s) specified in the command; if no canister name was specified, it will deploy all canisters listed in the
dfx.json
file.Compiles the code for each canister into a Wasm module.
Installs the Wasm module into each canister.
Deploys the canister(s) to the deployment endpoint of choice (local, playground, mainnet).
Output
Your deployed canister will now be executing two timers and printing the output directly to the terminal window:
2024-11-15 19:32:48.584899 UTC: [Canister bkyz2-fmaaa-aaaaa-qaaaq-cai] Generated new random proposal number: 133039
2024-11-15 19:32:51.197894 UTC: [Canister bkyz2-fmaaa-aaaaa-qaaaq-cai] Proposal info obtained through HTTPS outcall: {"action":"ManageNeuron","action_nns_function":null,"deadline_timestamp_seconds":1726953359,"decided_timestamp_seconds":1726783698,"executed_timestamp_seconds":1726783698,"failed_timestamp_seconds":0,"failure_reason":null,"id":113165,"known_neurons_ballots":[{"id":"28","name":"Internet Computer Association","vote":0},{"id":"27","name":"DFINITY Foundation","vote":0},
...
You can interact with the canister's public methods either in your web browser through the Candid UI URL that was returned in the deployment output or using the command line. Candid is an interface description language used to interact with a canister's public methods.
Upgrading canisters
Canisters can be upgraded, allowing the same canister ID to be retained for an application. Upgrades preserve the state of a canister while allowing you to change the code. However, canister upgrades clear the canister's Wasm memory. Any data not stored in stable memory will be removed.
In your backend canister source code file, make a change such as increasing the timer to 60 seconds rather than 30 seconds. Save the file.
Next, you must compile the updated canister code into a new Wasm module. dfx build
is used for compilation:
dfx build PROJECT_NAME_backend --network=local
Then, upgrade your canister to use the new Wasm module:
dfx canister install PROJECT_NAME_backend --network=local --mode upgrade
Output
Confirm that the change you made results in the expected functionality or behavior. Then, stop the canister:
dfx canister stop PROJECT_NAME_backend --network=local
Deploying your project to the mainnet
Now that the canister has been tested, you can deploy it to the mainnet. Deploying to the mainnet costs cycles.
Confirm that you are using the correct developer identity and that you have an available cycles balance:
dfx identity whoami
dfx cycles balance --network=ic
Then, deploy to the mainnet:
dfx deploy PROJECT_NAME_backend --network=ic
The flag --ic
is shorthand for --network=ic
.
The canister's Candid UI URL that is now hosted on the mainnet will be returned:
Deployed canisters.
URLs:
Backend canister via Candid interface:
PROJECT_NAME_backend: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=y4oop-liaaa-aaaab-qacha-cai
When a canister is running on the mainnet, you will always need to pass the --network=ic
flag to interact with it.
Canister settings
After a canister is deployed to the mainnet, it will constantly be consuming resources and cycles. To view information about how many resources and cycles currently being used, along with other information, view the canister's settings:
dfx canister status PROJECT_NAME_backend --network=ic
Output
Topping up canisters
A canister will burn cycles even in an idle state to pay for the network storage it uses. Additional costs will be charged whenever the canister sends and receives messages, uses compute resources, or uses special features like HTTPS outcalls and threshold signatures.
Even static canisters will eventually need to have their cycles balance replenished; otherwise, the canister will be deleted. This is known as "topping up" the canister.
Anyone can top up a canister. You do not need to be a controller of the canister to send it cycles.
To top up a canister, replace AMOUNT with the number of cycles to top up the canister with (i.e., 3T
to send 3 trillion cycles):
dfx cycles top-up PROJECT_NAME_backend AMOUNT --network ic
To check that your top up was successful, check the balance of the canister with dfx canister status PROJECT_NAME_backend --network=ic
.
Cycles management tools
Manually monitoring canisters to determine when they are getting close to the freezing threshold can be time-consuming and complicated if you have a project with many canisters. Several community tools exist to make monitoring canisters easy. Some of them allow you to set automation rules to automatically top up canisters if their cycles balance dips below a certain amount, while others provide a one-time top up workflow. Some of these tools include:
CycleOps: A comprehensive canister monitoring tool that provides top up automation, a statistics dashboard, email alerts, and the ability to create teams for synchronized management of collaborative projects.
ICPTopup.com: A simplified version of CycleOps that allows you to top up several canisters (up to 50) at one time.
Cycles freezing threshold
To prevent a canister from running out of cycles and being deleted, you can set what is known as a freezing threshold. This threshold is a duration of time set in seconds, indicating the minimum duration that the canister should exist without running out of cycles. Once a canister hits this threshold, it will not execute messages. It will only pay for the network resources it uses, such as compute allocation, memory usage, and storage allocation.
The default value of the freezing threshold is 2_592_000 (approximately 30 days). To change the freezing threshold, update the canister's settings with the command:
dfx canister update-settings PROJECT_NAME_backend --network=ic --freezing-threshold SECONDS
If you set a freezing threshold longer than 1.5 years, you will need to include an additional flag: --confirm-very-long-freezing-threshold
.
Canister logging
Canister logs can be used to gain insight into a canister's behavior and assist with debugging situations such as when a canister traps.
View your canister's logs:
dfx canister logs PROJECT_NAME_backend --network=ic
By default, canister logs are only visible to the canister's controllers, but they can be made public by updating the canister's settings:
dfx canister update-settings PROJECT_NAME_backend --network=ic --log-visibility public
Canister snapshots
Canister snapshots are used as a checkpoint that can be used to roll back your canister to a previous version in the event that the latest upgraded version becomes unresponsive or stops working as expected.
To create a canister snapshot, first stop your canister:
dfx canister stop PROJECT_NAME_backend --network=ic
Then, take a snapshot of the canister's current Wasm code and data.
The cost of a canister snapshot's memory consumption is charged to the canister itself.
dfx canister snapshot create PROJECT_NAME_backend --network=ic
Output
Currently, only one snapshot per canister can be saved. Taking another snapshot will overwrite the existing snapshot.
View details about this snapshot:
dfx canister snapshot list PROJECT_NAME_backend --network=ic
Output
Deleting a canister
Deleting a canister removes the canister identifier, code, and state. The canister's source code will still be stored in your local environment and can be deployed as a new canister at any time. A canister must be stopped before it can be deleted.
Any cycles remaining in the canister's balance will be returned to your developer identity.
dfx canister delete PROJECT_NAME_backend --network=ic
Stopping the local replica
To stop the local replica, simply use the dfx stop
command.
For unresponsive dfx
processes that are not stopped by dfx stop
, you can use dfx killall
to forcibly end them.
Getting help
To view help information for dfx
, you can use the dfx help
command or view the dfx
reference documentation.