diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bdd091b..529fae3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -** @dfinity/ninja-devs @dfinity/sdk \ No newline at end of file +** @dfinity/dx \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bee3f31..d23d1bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,126 +1,127 @@ -name: Create and publish a Docker image +name: Create and publish Docker images on: + workflow_dispatch: release: types: [published] -# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. env: REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - IMAGE_NAME_SLIM: ${{ github.repository }}-slim - IMAGE_NAME_AZLE: ${{ github.repository }}-azle + IMAGE_NAME_MOTOKO: ${{ github.repository }}-motoko + IMAGE_NAME_RUST: ${{ github.repository }}-rust + IMAGE_NAME_ALL: ${{ github.repository }}-all jobs: - build-and-push-image: + build-and-push-image-motoko: runs-on: ubuntu-latest - # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: contents: read packages: write steps: - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Log in to the Container registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. - # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. - # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MOTOKO }} + tags: | + type=raw,value=latest,enable=${{ github.event_name == 'release' }} + type=ref,event=branch + type=semver,pattern={{version}} + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build and push Docker image - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: - context: . + platforms: linux/amd64,linux/arm64 + context: motoko push: true tags: ${{ steps.meta.outputs.tags }} labels: | ${{ steps.meta.outputs.labels }} - org.opencontainers.image.description=A canister development environment for the Internet Computer (ICP) for Rust and Motoko. + org.opencontainers.image.description=A Motoko canister development environment for the Internet Computer (ICP) with icp-cli, moc, and mops. - build-and-push-image-azle: + build-and-push-image-rust: runs-on: ubuntu-latest - # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: contents: read packages: write steps: - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Log in to the Container registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_AZLE }} - # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. - # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. - # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_RUST }} + tags: | + type=raw,value=latest,enable=${{ github.event_name == 'release' }} + type=ref,event=branch + type=semver,pattern={{version}} + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build and push Docker image - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: - context: azle + platforms: linux/amd64,linux/arm64 + context: rust push: true tags: ${{ steps.meta.outputs.tags }} labels: | ${{ steps.meta.outputs.labels }} - org.opencontainers.image.description=A canister development environment for the Internet Computer (ICP) using Azle for TypeScript and JavaScript. + org.opencontainers.image.description=A Rust canister development environment for the Internet Computer (ICP) with icp-cli and Rust toolchain. - build-and-push-image-slim: + build-and-push-image-all: runs-on: ubuntu-latest - # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: contents: read packages: write steps: - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Log in to the Container registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SLIM }} - # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. - # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. - # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. - + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALL }} + tags: | + type=raw,value=latest,enable=${{ github.event_name == 'release' }} + type=ref,event=branch + type=semver,pattern={{version}} - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Build and push Docker image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: platforms: linux/amd64,linux/arm64 - context: slim + context: all push: true tags: ${{ steps.meta.outputs.tags }} labels: | ${{ steps.meta.outputs.labels }} - org.opencontainers.image.description=A slim canister development environment for the Internet Computer (ICP) for Rust and Motoko. + org.opencontainers.image.description=A combined Motoko and Rust canister development environment for the Internet Computer (ICP) with icp-cli, Rust toolchain, and mops. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index c497f31..0000000 --- a/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM --platform=linux/amd64 rust:1.83-slim-bookworm - -ENV NVM_DIR=/root/.nvm -ENV NVM_VERSION=v0.40.1 -ENV NODE_VERSION=22.10.0 -ENV POCKET_IC_SERVER_VERSION=8.0.0 -ENV POCKET_IC_PYTHON_VERSION=3.0.1 - -RUN apt -yq update -RUN apt -yqq install --no-install-recommends curl ca-certificates libunwind-dev git python3 python3-pip ssh - -# Install Node.js using nvm -ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}" -RUN curl --fail -sSf https://raw.githubusercontent.com/creationix/nvm/${NVM_VERSION}/install.sh | bash -RUN . "${NVM_DIR}/nvm.sh" && nvm install ${NODE_VERSION} -RUN . "${NVM_DIR}/nvm.sh" && nvm use v${NODE_VERSION} -RUN . "${NVM_DIR}/nvm.sh" && nvm alias default v${NODE_VERSION} - -# Install dfx -RUN DFX_VERSION=0.27.0 DFXVM_INIT_YES=true sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)" -ENV PATH="/root/.local/share/dfx/bin:$PATH" - -# Add wasm32-unknown-unknown target -RUN rustup target add wasm32-unknown-unknown - -# Install PocketIC Python -RUN pip3 install pocket-ic==${POCKET_IC_PYTHON_VERSION} --break-system-packages - -# Download the PocketIC server -RUN curl -Ls https://github.com/dfinity/pocketic/releases/download/${POCKET_IC_SERVER_VERSION}/pocket-ic-x86_64-linux.gz -o pocket-ic.gz -RUN gzip -d pocket-ic.gz -RUN chmod +x pocket-ic -RUN mv pocket-ic /usr/local/bin - -# Clean apt -RUN apt-get autoremove && apt-get clean diff --git a/README.md b/README.md index 6815bf4..2676eef 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,97 @@ # ICP Developer Environment -This repo contains Docker images that are used for setting up a remote, hybrid or local development environments for new developers on the Internet Computer. +Docker images for ICP canister development, designed for use with GitHub Codespaces and local dev containers. -## Usage -These container images can be used as a base for creating a dev container environment that targets ICP development. -Take a look at the repositories below to see dev containers in action: -- [Hello World Motoko with testing infrastructure](https://github.com/dfinity/icp-hello-world-motoko) -- [Hello World Rust with testing infrastructure](https://github.com/dfinity/icp-hello-world-rust) -- [Rust with React and Ethereum integration](https://github.com/fxgst/evm-rpc-rust) -- [Azle (JS/TS) with React](https://github.com/fxgst/azle-react) -- [Azle (JS/TS) Message Board Contract from dacadeorg](https://github.com/dacadeorg/icp-message-board-contract) -- [Azle (JS/TS) 201 from dacadeorg](https://github.com/dacadeorg/icp-azle-201) - -### Packages and Releases -On the right side, you will find new releases and the latest packages. -You can download the Docker image for Rust/Motoko with +## Images + +### `icp-dev-env-motoko` + +For Motoko canister development. + +| Tool | Version | +|---|---| +| [icp-cli](https://cli.internetcomputer.org) | 0.2.7 | +| [ic-wasm](https://github.com/dfinity/ic-wasm) | 0.9.11 | +| [mops](https://mops.one) | 2.13.2 | +| moc | installed per-project via `mops install` | +| Node.js | 24.15.0 | +| pnpm | 11.4.0 | ```bash -docker pull ghcr.io/dfinity/icp-dev-env:latest +docker pull ghcr.io/dfinity/icp-dev-env-motoko:latest # always current +docker pull ghcr.io/dfinity/icp-dev-env-motoko:1.0.0 # pinned ``` -or the one for [Azle](https://github.com/demergent-labs/azle) (JavaScript and TypeScript) with +### `icp-dev-env-rust` + +For Rust canister development. + +| Tool | Version | +|---|---| +| [icp-cli](https://cli.internetcomputer.org) | 0.2.7 | +| [ic-wasm](https://github.com/dfinity/ic-wasm) | 0.9.11 | +| Rust | 1.95.0 | +| wasm32-unknown-unknown target | — | +| Node.js | 24.15.0 | +| pnpm | 11.4.0 | ```bash -docker pull ghcr.io/dfinity/icp-dev-env-azle:latest +docker pull ghcr.io/dfinity/icp-dev-env-rust:latest # always current +docker pull ghcr.io/dfinity/icp-dev-env-rust:1.0.0 # pinned ``` -To download a specific version, add `:` at the end instead of `:latest`. +### `icp-dev-env-all` + +Combined Motoko and Rust development environment. Use this when your project includes both Motoko and Rust canisters. + +| Tool | Version | +|---|---| +| [icp-cli](https://cli.internetcomputer.org) | 0.2.7 | +| [ic-wasm](https://github.com/dfinity/ic-wasm) | 0.9.11 | +| [mops](https://mops.one) | 2.13.2 | +| moc | installed per-project via `mops install` | +| Rust | 1.95.0 | +| wasm32-unknown-unknown target | — | +| Node.js | 24.15.0 | +| pnpm | 11.4.0 | + +```bash +docker pull ghcr.io/dfinity/icp-dev-env-all:latest # always current +docker pull ghcr.io/dfinity/icp-dev-env-all:1.0.0 # pinned +``` + +## Usage + +Reference the image in your `.devcontainer/devcontainer.json`: + +```json +{ + "name": "My Example (Motoko)", + "image": "ghcr.io/dfinity/icp-dev-env-motoko:latest", + "workspaceFolder": "/workspaces/examples/motoko/my-example", + "forwardPorts": [8000], + "portsAttributes": { + "8000": { "label": "ICP local network", "onAutoForward": "ignore" } + }, + "postCreateCommand": "mops install", + "postStartCommand": "icp network start -d", + "customizations": { + "vscode": { + "extensions": ["dfinity-foundation.vscode-motoko", "stateful.runme"] + } + } +} +``` + +See [dfinity/examples](https://github.com/dfinity/examples) for full usage across all examples. + +## Releasing + +Tool versions are pinned via `ARG` in each Dockerfile. To update a version: + +1. Update the relevant `ARG` in the affected Dockerfile(s) (`motoko/Dockerfile`, `rust/Dockerfile`, `all/Dockerfile`) +2. Create a new GitHub Release with a semver tag (e.g. `v1.0.1`) — the CI pipeline builds and pushes all images to GHCR + +Images are built for `linux/amd64` and `linux/arm64`. -## Creating a new Release -To release a new version of both images, create a new tag with the corresponding version number. -The CI pipeline will automatically build and push the new images to the GitHub Container Registry (ghcr.io). +> **Note:** The release must be published as non-draft to trigger the CI pipeline. diff --git a/all/Dockerfile b/all/Dockerfile new file mode 100644 index 0000000..54bd350 --- /dev/null +++ b/all/Dockerfile @@ -0,0 +1,33 @@ +FROM rust:1.95.0-slim-bookworm + +ARG NODE_VERSION=24.15.0 +ARG NVM_VERSION=v0.40.1 +ARG PNPM_VERSION=11.4.0 +ARG ICP_CLI_VERSION=0.2.7 +ARG IC_WASM_VERSION=0.9.11 +ARG IC_MOPS_VERSION=2.13.2 + +ENV NVM_DIR=/root/.nvm +ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}" + +RUN apt-get -yq update && apt-get -yq upgrade && apt-get -yqq install --no-install-recommends \ + curl ca-certificates git jq make libdbus-1-3 && \ + apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Node.js via nvm (required for icp-cli, ic-wasm, mops) +RUN curl --fail -sSf https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash && \ + . "${NVM_DIR}/nvm.sh" && \ + nvm install ${NODE_VERSION} && \ + nvm alias default ${NODE_VERSION} + +# pnpm +RUN npm install -g pnpm@${PNPM_VERSION} + +# icp-cli + ic-wasm +RUN npm install -g @icp-sdk/icp-cli@${ICP_CLI_VERSION} @icp-sdk/ic-wasm@${IC_WASM_VERSION} + +# wasm32 target for Rust canister compilation +RUN rustup target add wasm32-unknown-unknown + +# mops (Motoko package manager) — moc is installed per-project via mops install +RUN npm install -g ic-mops@${IC_MOPS_VERSION} diff --git a/azle/Dockerfile b/azle/Dockerfile deleted file mode 100644 index e192d77..0000000 --- a/azle/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM --platform=linux/amd64 node:slim - -RUN apt -yq update -RUN apt -yqq install --no-install-recommends curl ca-certificates libunwind-dev git python3 - -# Install dfx -RUN DFX_VERSION=0.27.0 DFXVM_INIT_YES=true sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)" -ENV PATH="/root/.local/share/dfx/bin:$PATH" - -# Clean apt -RUN apt-get autoremove && apt-get clean diff --git a/motoko/Dockerfile b/motoko/Dockerfile new file mode 100644 index 0000000..32ee262 --- /dev/null +++ b/motoko/Dockerfile @@ -0,0 +1,30 @@ +FROM debian:bookworm-slim + +ARG NODE_VERSION=24.15.0 +ARG NVM_VERSION=v0.40.1 +ARG PNPM_VERSION=11.4.0 +ARG ICP_CLI_VERSION=0.2.7 +ARG IC_WASM_VERSION=0.9.11 +ARG IC_MOPS_VERSION=2.13.2 + +ENV NVM_DIR=/root/.nvm +ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}" + +RUN apt-get -yq update && apt-get -yq upgrade && apt-get -yqq install --no-install-recommends \ + curl ca-certificates git jq make libdbus-1-3 && \ + apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Node.js via nvm (required for icp-cli, ic-wasm, mops) +RUN curl --fail -sSf https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash && \ + . "${NVM_DIR}/nvm.sh" && \ + nvm install ${NODE_VERSION} && \ + nvm alias default ${NODE_VERSION} + +# pnpm +RUN npm install -g pnpm@${PNPM_VERSION} + +# icp-cli + ic-wasm +RUN npm install -g @icp-sdk/icp-cli@${ICP_CLI_VERSION} @icp-sdk/ic-wasm@${IC_WASM_VERSION} + +# mops (Motoko package manager) — moc is installed per-project via mops install +RUN npm install -g ic-mops@${IC_MOPS_VERSION} diff --git a/rust/Dockerfile b/rust/Dockerfile new file mode 100644 index 0000000..c225553 --- /dev/null +++ b/rust/Dockerfile @@ -0,0 +1,29 @@ +FROM rust:1.95.0-slim-bookworm + +ARG NODE_VERSION=24.15.0 +ARG NVM_VERSION=v0.40.1 +ARG PNPM_VERSION=11.4.0 +ARG ICP_CLI_VERSION=0.2.7 +ARG IC_WASM_VERSION=0.9.11 + +ENV NVM_DIR=/root/.nvm +ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}" + +RUN apt-get -yq update && apt-get -yq upgrade && apt-get -yqq install --no-install-recommends \ + curl ca-certificates git jq make libdbus-1-3 && \ + apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Node.js via nvm (required for icp-cli and ic-wasm) +RUN curl --fail -sSf https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash && \ + . "${NVM_DIR}/nvm.sh" && \ + nvm install ${NODE_VERSION} && \ + nvm alias default ${NODE_VERSION} + +# pnpm +RUN npm install -g pnpm@${PNPM_VERSION} + +# icp-cli + ic-wasm +RUN npm install -g @icp-sdk/icp-cli@${ICP_CLI_VERSION} @icp-sdk/ic-wasm@${IC_WASM_VERSION} + +# wasm32 target for canister compilation +RUN rustup target add wasm32-unknown-unknown diff --git a/slim/Dockerfile b/slim/Dockerfile deleted file mode 100644 index f8bb6a9..0000000 --- a/slim/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM rust:1.89-slim-bookworm - -ENV NVM_DIR=/root/.nvm -ENV NVM_VERSION=v0.40.1 -ENV NODE_VERSION=22.10.0 -ENV IC_MOPS_VERSION=1.11.1 -ENV CANDID_EXTRACTOR_VERSION=0.1.6 - -RUN apt -yq update -RUN apt -yqq install --no-install-recommends curl ca-certificates libunwind-dev git - -# Install Node.js using nvm -ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}" -RUN curl --fail -sSf https://raw.githubusercontent.com/creationix/nvm/${NVM_VERSION}/install.sh | bash -RUN . "${NVM_DIR}/nvm.sh" && nvm install ${NODE_VERSION} -RUN . "${NVM_DIR}/nvm.sh" && nvm use v${NODE_VERSION} -RUN . "${NVM_DIR}/nvm.sh" && nvm alias default v${NODE_VERSION} - -# Install ic-mops -RUN npm install -g ic-mops@${IC_MOPS_VERSION} - -# Install dfx -RUN DFX_VERSION=0.29.0 DFXVM_INIT_YES=true sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)" -ENV PATH="/root/.local/share/dfx/bin:$PATH" - -# Add wasm32-unknown-unknown target -RUN rustup target add wasm32-unknown-unknown - -# Install candid-extractor -RUN cargo install candid-extractor --version ${CANDID_EXTRACTOR_VERSION} - -# Clean apt -RUN apt-get autoremove && apt-get clean