From 809b1cf1072f50782aa67d2c3b3eab91e57ca16a Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 11:24:45 +0200 Subject: [PATCH 01/14] feat: add Motoko and Rust images with icp-cli (pilot for Codespaces) Adds two new language-specific Docker images replacing dfx with icp-cli: - motoko/Dockerfile: icp-cli, ic-wasm, moc 1.5.1, mops, Node.js, pnpm - rust/Dockerfile: icp-cli, ic-wasm, Rust toolchain, wasm32 target, Node.js, pnpm Updates CI to trigger on workflow_dispatch and pushes to feat/icp-cli-images in addition to releases. New motoko and rust jobs publish multi-platform (amd64 + arm64) images tagged :dev from this branch, semver from releases. This is a pilot for advertising GitHub Codespaces instead of ICP Ninja / short-lived mainnet deployments. See dfinity/examples#1345. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 106 ++++++++++++++++++++++++++++++--------- motoko/Dockerfile | 35 +++++++++++++ rust/Dockerfile | 28 +++++++++++ 3 files changed, 146 insertions(+), 23 deletions(-) create mode 100644 motoko/Dockerfile create mode 100644 rust/Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bee3f31..696a9b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,42 +1,41 @@ -name: Create and publish a Docker image +name: Create and publish Docker images on: + workflow_dispatch: + push: + branches: + - feat/icp-cli-images 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 jobs: build-and-push-image: 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. - name: Log in to the Container registry uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.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 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. - name: Build and push Docker image uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: @@ -49,29 +48,23 @@ jobs: build-and-push-image-azle: 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. - name: Log in to the Container registry uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.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 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. - name: Build and push Docker image uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: @@ -84,36 +77,27 @@ jobs: build-and-push-image-slim: 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. - name: Log in to the Container registry uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.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 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. - - name: Set up QEMU uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - - name: Build and push Docker image uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: @@ -124,3 +108,79 @@ jobs: labels: | ${{ steps.meta.outputs.labels }} org.opencontainers.image.description=A slim canister development environment for the Internet Computer (ICP) for Rust and Motoko. + + build-and-push-image-motoko: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - name: Log in to the Container registry + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MOTOKO }} + tags: | + type=raw,value=dev,enable=${{ github.ref_name == 'feat/icp-cli-images' }} + type=ref,event=branch + type=semver,pattern={{version}} + - name: Set up QEMU + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + - name: Build and push Docker image + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + platforms: linux/amd64,linux/arm64 + context: motoko + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: | + ${{ steps.meta.outputs.labels }} + org.opencontainers.image.description=A Motoko canister development environment for the Internet Computer (ICP) with icp-cli, moc, and mops. + + build-and-push-image-rust: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - name: Log in to the Container registry + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_RUST }} + tags: | + type=raw,value=dev,enable=${{ github.ref_name == 'feat/icp-cli-images' }} + type=ref,event=branch + type=semver,pattern={{version}} + - name: Set up QEMU + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + - name: Build and push Docker image + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + platforms: linux/amd64,linux/arm64 + context: rust + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: | + ${{ steps.meta.outputs.labels }} + org.opencontainers.image.description=A Rust canister development environment for the Internet Computer (ICP) with icp-cli and Rust toolchain. diff --git a/motoko/Dockerfile b/motoko/Dockerfile new file mode 100644 index 0000000..ffa1427 --- /dev/null +++ b/motoko/Dockerfile @@ -0,0 +1,35 @@ +FROM debian:bookworm-slim + +ARG NODE_VERSION=22.10.0 +ARG NVM_VERSION=v0.40.1 +ARG MOC_VERSION=1.5.1 +ARG ICP_CLI_VERSION=latest +ARG IC_WASM_VERSION=latest +ARG IC_MOPS_VERSION=1.11.1 + +ENV NVM_DIR=/root/.nvm +ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}" +ENV MOPS_CACHE=/root/.cache/mops + +RUN apt-get -yq update && apt-get -yqq install --no-install-recommends \ + curl ca-certificates git libunwind-dev && \ + 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 + +# 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) +RUN npm install -g ic-mops@${IC_MOPS_VERSION} + +# moc (Motoko compiler) via mops toolchain — installs to /root/.cache/mops/moc/{version}/moc +RUN mops toolchain use moc ${MOC_VERSION} && \ + ln -sf /root/.cache/mops/moc/${MOC_VERSION}/moc /usr/local/bin/moc diff --git a/rust/Dockerfile b/rust/Dockerfile new file mode 100644 index 0000000..0936e64 --- /dev/null +++ b/rust/Dockerfile @@ -0,0 +1,28 @@ +FROM rust:1.89-slim-bookworm + +ARG NODE_VERSION=22.10.0 +ARG NVM_VERSION=v0.40.1 +ARG ICP_CLI_VERSION=latest +ARG IC_WASM_VERSION=latest + +ENV NVM_DIR=/root/.nvm +ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}" + +RUN apt-get -yq update && apt-get -yqq install --no-install-recommends \ + curl ca-certificates git libunwind-dev && \ + 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 + +# 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 From 5adc7ee080347f6122208ece70799aefcbfdd179 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 11:32:18 +0200 Subject: [PATCH 02/14] chore: pin tool versions, switch to ubuntu:24.04, clean up legacy CI jobs - Pin all tool versions: icp-cli 0.2.7, ic-wasm 0.9.11, ic-mops 2.13.2, moc 1.8.1 - Switch base image from debian:bookworm-slim to ubuntu:24.04 (fewer unfixed CVEs) - Drop libunwind-dev (not required by icp-cli, mops, or moc) - Add apt-get upgrade to apply all available security patches at build time - Install Rust via rustup instead of using the rust: base image - Remove legacy base/slim/azle CI jobs from fork (dfx-based, irrelevant to pilot) Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 95 ---------------------------------------- motoko/Dockerfile | 14 +++--- rust/Dockerfile | 20 +++++---- 3 files changed, 18 insertions(+), 111 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 696a9b0..36f99cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,105 +10,10 @@ on: 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 jobs: - build-and-push-image: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - name: Log in to the Container registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - name: Build and push Docker image - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 - with: - context: . - 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. - - build-and-push-image-azle: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - name: Log in to the Container registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_AZLE }} - - name: Build and push Docker image - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 - with: - context: azle - 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. - - build-and-push-image-slim: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - name: Log in to the Container registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SLIM }} - - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - - name: Build and push Docker image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 - with: - platforms: linux/amd64,linux/arm64 - context: slim - 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. - build-and-push-image-motoko: runs-on: ubuntu-latest permissions: diff --git a/motoko/Dockerfile b/motoko/Dockerfile index ffa1427..eea068c 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -1,18 +1,18 @@ -FROM debian:bookworm-slim +FROM ubuntu:24.04 ARG NODE_VERSION=22.10.0 ARG NVM_VERSION=v0.40.1 -ARG MOC_VERSION=1.5.1 -ARG ICP_CLI_VERSION=latest -ARG IC_WASM_VERSION=latest -ARG IC_MOPS_VERSION=1.11.1 +ARG MOC_VERSION=1.8.1 +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}" ENV MOPS_CACHE=/root/.cache/mops -RUN apt-get -yq update && apt-get -yqq install --no-install-recommends \ - curl ca-certificates git libunwind-dev && \ +RUN apt-get -yq update && apt-get -yq upgrade && apt-get -yqq install --no-install-recommends \ + curl ca-certificates git && \ apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* # Node.js via nvm (required for icp-cli, ic-wasm, mops) diff --git a/rust/Dockerfile b/rust/Dockerfile index 0936e64..d6a8f51 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -1,17 +1,22 @@ -FROM rust:1.89-slim-bookworm +FROM ubuntu:24.04 ARG NODE_VERSION=22.10.0 ARG NVM_VERSION=v0.40.1 -ARG ICP_CLI_VERSION=latest -ARG IC_WASM_VERSION=latest +ARG RUST_VERSION=1.89.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}" +ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin:/root/.cargo/bin:${PATH}" -RUN apt-get -yq update && apt-get -yqq install --no-install-recommends \ - curl ca-certificates git libunwind-dev && \ +RUN apt-get -yq update && apt-get -yq upgrade && apt-get -yqq install --no-install-recommends \ + curl ca-certificates git && \ apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* +# Rust via rustup +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ + sh -s -- -y --default-toolchain ${RUST_VERSION} --target wasm32-unknown-unknown + # 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" && \ @@ -23,6 +28,3 @@ RUN npm install -g pnpm # 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 From d72d85a3b57d6e5c8afce6b96e5c31fdffd57f81 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 11:34:27 +0200 Subject: [PATCH 03/14] chore: revert to slim base images (debian:bookworm-slim, rust:slim-bookworm) ubuntu:24.04 is larger than the slim variants and offers no meaningful CVE reduction over debian:bookworm-slim after apt-get upgrade. Remaining CVEs post-upgrade are unfixed upstream and present in any standard base image. Co-Authored-By: Claude Sonnet 4.6 --- motoko/Dockerfile | 2 +- rust/Dockerfile | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/motoko/Dockerfile b/motoko/Dockerfile index eea068c..019edc5 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:24.04 +FROM debian:bookworm-slim ARG NODE_VERSION=22.10.0 ARG NVM_VERSION=v0.40.1 diff --git a/rust/Dockerfile b/rust/Dockerfile index d6a8f51..3f4160c 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -1,22 +1,17 @@ -FROM ubuntu:24.04 +FROM rust:1.89-slim-bookworm ARG NODE_VERSION=22.10.0 ARG NVM_VERSION=v0.40.1 -ARG RUST_VERSION=1.89.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:/root/.cargo/bin:${PATH}" +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 && \ apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* -# Rust via rustup -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ - sh -s -- -y --default-toolchain ${RUST_VERSION} --target wasm32-unknown-unknown - # 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" && \ @@ -28,3 +23,6 @@ RUN npm install -g pnpm # 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 From c43a7300d20defddfa70830b3b8afa64f20c33ce Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 11:36:11 +0200 Subject: [PATCH 04/14] chore: remove legacy dfx-based images, rewrite README Removes the three dfx-based images that are no longer needed: - Dockerfile (root): base image, amd64-only, dfx 0.27 + PocketIC Python - slim/Dockerfile: slim multi-platform image, dfx 0.29 (referenced by examples) - azle/Dockerfile: Azle (JS/TS) image, dfx 0.27 The repo now contains only the two new icp-cli-based images: - motoko/Dockerfile - rust/Dockerfile Updates README to document the new images, their tool versions, a devcontainer.json usage example, and the release process. Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 36 ---------------------- README.md | 82 ++++++++++++++++++++++++++++++++++++------------- azle/Dockerfile | 11 ------- slim/Dockerfile | 33 -------------------- 4 files changed, 61 insertions(+), 101 deletions(-) delete mode 100644 Dockerfile delete mode 100644 azle/Dockerfile delete mode 100644 slim/Dockerfile 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..94a2425 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,73 @@ # 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 | +| [moc](https://github.com/dfinity/motoko) | 1.8.1 | +| [mops](https://mops.one) | 2.13.2 | +| Node.js | 22.10.0 | +| pnpm | latest | ```bash -docker pull ghcr.io/dfinity/icp-dev-env:latest +docker pull ghcr.io/dfinity/icp-dev-env-motoko:latest ``` -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.89 | +| wasm32-unknown-unknown target | — | +| Node.js | 22.10.0 | +| pnpm | latest | ```bash -docker pull ghcr.io/dfinity/icp-dev-env-azle:latest +docker pull ghcr.io/dfinity/icp-dev-env-rust:latest +``` + +## 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"] + } + } +} ``` -To download a specific version, add `:` at the end instead of `:latest`. +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 `motoko/Dockerfile` and/or `rust/Dockerfile` +2. Create a new GitHub release — the CI pipeline builds and pushes both images to GHCR -## 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). +Images are built for `linux/amd64` and `linux/arm64`. 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/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 From 147d4142aa63d0b3d9aedd501a1930b51f96abf6 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 11:48:42 +0200 Subject: [PATCH 05/14] =?UTF-8?q?fix:=20remove=20moc=20from=20image=20?= =?UTF-8?q?=E2=80=94=20installed=20per-project=20via=20mops=20install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mops install (run in postCreateCommand) handles the [toolchain] section of each example's mops.toml and installs the correct moc version automatically. Pre-installing moc in the image is not needed. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 2 +- motoko/Dockerfile | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 94a2425..8a51981 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ For Motoko canister development. |---|---| | [icp-cli](https://cli.internetcomputer.org) | 0.2.7 | | [ic-wasm](https://github.com/dfinity/ic-wasm) | 0.9.11 | -| [moc](https://github.com/dfinity/motoko) | 1.8.1 | | [mops](https://mops.one) | 2.13.2 | +| moc | installed per-project via `mops install` | | Node.js | 22.10.0 | | pnpm | latest | diff --git a/motoko/Dockerfile b/motoko/Dockerfile index 019edc5..3b9b7bb 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -2,14 +2,12 @@ FROM debian:bookworm-slim ARG NODE_VERSION=22.10.0 ARG NVM_VERSION=v0.40.1 -ARG MOC_VERSION=1.8.1 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}" -ENV MOPS_CACHE=/root/.cache/mops RUN apt-get -yq update && apt-get -yq upgrade && apt-get -yqq install --no-install-recommends \ curl ca-certificates git && \ @@ -27,9 +25,5 @@ RUN npm install -g pnpm # 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) +# mops (Motoko package manager) — moc is installed per-project via mops install RUN npm install -g ic-mops@${IC_MOPS_VERSION} - -# moc (Motoko compiler) via mops toolchain — installs to /root/.cache/mops/moc/{version}/moc -RUN mops toolchain use moc ${MOC_VERSION} && \ - ln -sf /root/.cache/mops/moc/${MOC_VERSION}/moc /usr/local/bin/moc From db4f77e82a65adb044cfce24b045d0e02b99aa03 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 11:55:55 +0200 Subject: [PATCH 06/14] =?UTF-8?q?chore:=20Node.js=2022=20=E2=86=92=2024.15?= =?UTF-8?q?.0,=20bump=20all=20GitHub=20Actions=20to=20Node.js=2024=20versi?= =?UTF-8?q?ons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Node.js 22.10.0 → 24.15.0 in both Dockerfiles and README - actions/checkout v4 → v6.0.2 - docker/login-action v3 → v4.1.0 - docker/metadata-action v5 → v6.0.0 - docker/setup-qemu-action v3 → v4.0.0 - docker/setup-buildx-action v3 → v4.0.0 - docker/build-push-action v6 → v7.1.0 All actions previously ran on Node.js 20 which is deprecated on GitHub Actions runners from June 2026. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 24 ++++++++++++------------ README.md | 4 ++-- motoko/Dockerfile | 2 +- rust/Dockerfile | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36f99cd..65733da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,16 +21,16 @@ jobs: packages: write steps: - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + 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 }} - 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_MOTOKO }} tags: | @@ -38,11 +38,11 @@ jobs: 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: motoko @@ -59,16 +59,16 @@ jobs: packages: write steps: - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + 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 }} - 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_RUST }} tags: | @@ -76,11 +76,11 @@ jobs: 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: rust diff --git a/README.md b/README.md index 8a51981..677f841 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ For Motoko canister development. | [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 | 22.10.0 | +| Node.js | 24.15.0 | | pnpm | latest | ```bash @@ -31,7 +31,7 @@ For Rust canister development. | [ic-wasm](https://github.com/dfinity/ic-wasm) | 0.9.11 | | Rust | 1.89 | | wasm32-unknown-unknown target | — | -| Node.js | 22.10.0 | +| Node.js | 24.15.0 | | pnpm | latest | ```bash diff --git a/motoko/Dockerfile b/motoko/Dockerfile index 3b9b7bb..0c9f9a8 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -1,6 +1,6 @@ FROM debian:bookworm-slim -ARG NODE_VERSION=22.10.0 +ARG NODE_VERSION=24.15.0 ARG NVM_VERSION=v0.40.1 ARG ICP_CLI_VERSION=0.2.7 ARG IC_WASM_VERSION=0.9.11 diff --git a/rust/Dockerfile b/rust/Dockerfile index 3f4160c..2d69883 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -1,6 +1,6 @@ FROM rust:1.89-slim-bookworm -ARG NODE_VERSION=22.10.0 +ARG NODE_VERSION=24.15.0 ARG NVM_VERSION=v0.40.1 ARG ICP_CLI_VERSION=0.2.7 ARG IC_WASM_VERSION=0.9.11 From 3f606e76d078b0c582ecbf5340a5c817cb0132ba Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 11:56:20 +0200 Subject: [PATCH 07/14] =?UTF-8?q?chore:=20bump=20Rust=201.89=20=E2=86=92?= =?UTF-8?q?=201.95.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- README.md | 2 +- rust/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 677f841..c94079d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ For Rust canister development. |---|---| | [icp-cli](https://cli.internetcomputer.org) | 0.2.7 | | [ic-wasm](https://github.com/dfinity/ic-wasm) | 0.9.11 | -| Rust | 1.89 | +| Rust | 1.95.0 | | wasm32-unknown-unknown target | — | | Node.js | 24.15.0 | | pnpm | latest | diff --git a/rust/Dockerfile b/rust/Dockerfile index 2d69883..0d180d9 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.89-slim-bookworm +FROM rust:1.95.0-slim-bookworm ARG NODE_VERSION=24.15.0 ARG NVM_VERSION=v0.40.1 From 5e4ec1db719ee54d1816ccac4380b3f5776ecbce Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 12:53:19 +0200 Subject: [PATCH 08/14] fix: add libdbus-1-3 to both images icp-cli links against libdbus-1.so.3 at runtime; missing from debian:bookworm-slim and rust:slim-bookworm base images. Co-Authored-By: Claude Sonnet 4.6 --- motoko/Dockerfile | 2 +- rust/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/motoko/Dockerfile b/motoko/Dockerfile index 0c9f9a8..7c750b7 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -10,7 +10,7 @@ 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 && \ + curl ca-certificates git 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) diff --git a/rust/Dockerfile b/rust/Dockerfile index 0d180d9..5f0ec72 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -9,7 +9,7 @@ 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 && \ + curl ca-certificates git 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) From f77b05171470b673f45239be740a5ce7ae635dd0 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 21 May 2026 15:02:02 +0200 Subject: [PATCH 09/14] chore: add jq to both images Co-Authored-By: Claude Sonnet 4.6 --- motoko/Dockerfile | 2 +- rust/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/motoko/Dockerfile b/motoko/Dockerfile index 7c750b7..0de3731 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -10,7 +10,7 @@ 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 libdbus-1-3 && \ + curl ca-certificates git jq 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) diff --git a/rust/Dockerfile b/rust/Dockerfile index 5f0ec72..2adf859 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -9,7 +9,7 @@ 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 libdbus-1-3 && \ + curl ca-certificates git jq 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) From e08165343decb6c2a3c19fca9108d57feba54ba5 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Fri, 22 May 2026 08:12:04 +0200 Subject: [PATCH 10/14] feat: add combined Motoko + Rust image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds all/Dockerfile based on rust:slim-bookworm with mops layered on top. Intended as the default devcontainer image when opening the examples repo root — lets developers work across both Motoko and Rust examples without switching environments. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 39 +++++++++++++++++++++++++++++++++++++++ all/Dockerfile | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 all/Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65733da..da6d934 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ env: REGISTRY: ghcr.io IMAGE_NAME_MOTOKO: ${{ github.repository }}-motoko IMAGE_NAME_RUST: ${{ github.repository }}-rust + IMAGE_NAME_ALL: ${{ github.repository }}-all jobs: build-and-push-image-motoko: @@ -89,3 +90,41 @@ jobs: labels: | ${{ steps.meta.outputs.labels }} org.opencontainers.image.description=A Rust canister development environment for the Internet Computer (ICP) with icp-cli and Rust toolchain. + + build-and-push-image-all: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Log in to the Container registry + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALL }} + tags: | + type=raw,value=dev,enable=${{ github.ref_name == 'feat/icp-cli-images' }} + 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@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + with: + platforms: linux/amd64,linux/arm64 + context: all + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: | + ${{ steps.meta.outputs.labels }} + 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/all/Dockerfile b/all/Dockerfile new file mode 100644 index 0000000..b213f24 --- /dev/null +++ b/all/Dockerfile @@ -0,0 +1,32 @@ +FROM rust:1.95.0-slim-bookworm + +ARG NODE_VERSION=24.15.0 +ARG NVM_VERSION=v0.40.1 +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 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 + +# 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} From 2dbd73e59855b6a99461af3ceb2dab97ab6ab60b Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Fri, 22 May 2026 13:02:39 +0200 Subject: [PATCH 11/14] fix: add make to all images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI workflows run `make test` after deploying — make was missing from the apt packages in all three images. Co-Authored-By: Claude Sonnet 4.6 --- all/Dockerfile | 2 +- motoko/Dockerfile | 2 +- rust/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/all/Dockerfile b/all/Dockerfile index b213f24..4767679 100644 --- a/all/Dockerfile +++ b/all/Dockerfile @@ -10,7 +10,7 @@ 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 libdbus-1-3 && \ + 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) diff --git a/motoko/Dockerfile b/motoko/Dockerfile index 0de3731..c9f2a61 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -10,7 +10,7 @@ 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 libdbus-1-3 && \ + 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) diff --git a/rust/Dockerfile b/rust/Dockerfile index 2adf859..bcdfad3 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -9,7 +9,7 @@ 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 libdbus-1-3 && \ + 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) From a87d9c18a7d0de31303802333ccc1cbb9bb12636 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Fri, 29 May 2026 02:07:14 +0200 Subject: [PATCH 12/14] fix: remove auto-publish push trigger, keep only release + workflow_dispatch Publishing images to the dfinity org on every push to the branch is unacceptable. Images should only be published on an explicit release or manual dispatch. Also removes the :dev raw tag which was only meaningful in the now-removed branch-push context. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da6d934..dcfc256 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,6 @@ name: Create and publish Docker images on: workflow_dispatch: - push: - branches: - - feat/icp-cli-images release: types: [published] @@ -35,7 +32,6 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MOTOKO }} tags: | - type=raw,value=dev,enable=${{ github.ref_name == 'feat/icp-cli-images' }} type=ref,event=branch type=semver,pattern={{version}} - name: Set up QEMU @@ -73,7 +69,6 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_RUST }} tags: | - type=raw,value=dev,enable=${{ github.ref_name == 'feat/icp-cli-images' }} type=ref,event=branch type=semver,pattern={{version}} - name: Set up QEMU @@ -111,7 +106,6 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALL }} tags: | - type=raw,value=dev,enable=${{ github.ref_name == 'feat/icp-cli-images' }} type=ref,event=branch type=semver,pattern={{version}} - name: Set up QEMU From 8f72032824e65657530d1cf71680fdf9e7fe51ca Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Fri, 29 May 2026 02:26:05 +0200 Subject: [PATCH 13/14] docs: fix README accuracy, add icp-dev-env-all, update CODEOWNERS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace :latest tag references with semver (1.0.0) — :latest is not produced by the CI workflow - Add icp-dev-env-all image section (was missing entirely) - Fix Releasing section: "both images" → "all images", list all three Dockerfiles, note release must be non-draft - Update CODEOWNERS: replace @dfinity/ninja-devs @dfinity/sdk with @dfinity/dx Co-Authored-By: Claude Sonnet 4.6 --- .github/CODEOWNERS | 2 +- README.md | 31 ++++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) 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/README.md b/README.md index c94079d..1d46eeb 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ For Motoko canister development. | pnpm | latest | ```bash -docker pull ghcr.io/dfinity/icp-dev-env-motoko:latest +docker pull ghcr.io/dfinity/icp-dev-env-motoko:1.0.0 ``` ### `icp-dev-env-rust` @@ -35,7 +35,26 @@ For Rust canister development. | pnpm | latest | ```bash -docker pull ghcr.io/dfinity/icp-dev-env-rust:latest +docker pull ghcr.io/dfinity/icp-dev-env-rust:1.0.0 +``` + +### `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 | latest | + +```bash +docker pull ghcr.io/dfinity/icp-dev-env-all:1.0.0 ``` ## Usage @@ -45,7 +64,7 @@ Reference the image in your `.devcontainer/devcontainer.json`: ```json { "name": "My Example (Motoko)", - "image": "ghcr.io/dfinity/icp-dev-env-motoko:latest", + "image": "ghcr.io/dfinity/icp-dev-env-motoko:1.0.0", "workspaceFolder": "/workspaces/examples/motoko/my-example", "forwardPorts": [8000], "portsAttributes": { @@ -67,7 +86,9 @@ See [dfinity/examples](https://github.com/dfinity/examples) for full usage acros Tool versions are pinned via `ARG` in each Dockerfile. To update a version: -1. Update the relevant `ARG` in `motoko/Dockerfile` and/or `rust/Dockerfile` -2. Create a new GitHub release — the CI pipeline builds and pushes both images to GHCR +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`. + +> **Note:** The release must be published as non-draft to trigger the CI pipeline. From b94111f978fc28d63419fa3e96c24818985d5ba2 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Fri, 29 May 2026 10:23:49 +0200 Subject: [PATCH 14/14] chore: pin pnpm version, add :latest tag on release, update docs - Add PNPM_VERSION=11.4.0 ARG to all three Dockerfiles; pnpm has no LTS channel so we pin to current stable like all other tools - CI now publishes :latest alongside the semver tag on GitHub Release - README: replace "pnpm latest" with pinned version in tool tables, show both :latest and pinned pull commands per image Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 3 +++ README.md | 17 ++++++++++------- all/Dockerfile | 3 ++- motoko/Dockerfile | 3 ++- rust/Dockerfile | 3 ++- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dcfc256..d23d1bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,7 @@ jobs: with: 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 @@ -69,6 +70,7 @@ jobs: with: 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 @@ -106,6 +108,7 @@ jobs: with: 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 diff --git a/README.md b/README.md index 1d46eeb..2676eef 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,11 @@ For Motoko canister development. | [mops](https://mops.one) | 2.13.2 | | moc | installed per-project via `mops install` | | Node.js | 24.15.0 | -| pnpm | latest | +| pnpm | 11.4.0 | ```bash -docker pull ghcr.io/dfinity/icp-dev-env-motoko:1.0.0 +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 ``` ### `icp-dev-env-rust` @@ -32,10 +33,11 @@ For Rust canister development. | Rust | 1.95.0 | | wasm32-unknown-unknown target | — | | Node.js | 24.15.0 | -| pnpm | latest | +| pnpm | 11.4.0 | ```bash -docker pull ghcr.io/dfinity/icp-dev-env-rust:1.0.0 +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 ``` ### `icp-dev-env-all` @@ -51,10 +53,11 @@ Combined Motoko and Rust development environment. Use this when your project inc | Rust | 1.95.0 | | wasm32-unknown-unknown target | — | | Node.js | 24.15.0 | -| pnpm | latest | +| pnpm | 11.4.0 | ```bash -docker pull ghcr.io/dfinity/icp-dev-env-all:1.0.0 +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 @@ -64,7 +67,7 @@ Reference the image in your `.devcontainer/devcontainer.json`: ```json { "name": "My Example (Motoko)", - "image": "ghcr.io/dfinity/icp-dev-env-motoko:1.0.0", + "image": "ghcr.io/dfinity/icp-dev-env-motoko:latest", "workspaceFolder": "/workspaces/examples/motoko/my-example", "forwardPorts": [8000], "portsAttributes": { diff --git a/all/Dockerfile b/all/Dockerfile index 4767679..54bd350 100644 --- a/all/Dockerfile +++ b/all/Dockerfile @@ -2,6 +2,7 @@ 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 @@ -20,7 +21,7 @@ RUN curl --fail -sSf https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION} nvm alias default ${NODE_VERSION} # pnpm -RUN npm install -g 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} diff --git a/motoko/Dockerfile b/motoko/Dockerfile index c9f2a61..32ee262 100644 --- a/motoko/Dockerfile +++ b/motoko/Dockerfile @@ -2,6 +2,7 @@ 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 @@ -20,7 +21,7 @@ RUN curl --fail -sSf https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION} nvm alias default ${NODE_VERSION} # pnpm -RUN npm install -g 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} diff --git a/rust/Dockerfile b/rust/Dockerfile index bcdfad3..c225553 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -2,6 +2,7 @@ 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 @@ -19,7 +20,7 @@ RUN curl --fail -sSf https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION} nvm alias default ${NODE_VERSION} # pnpm -RUN npm install -g 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}