Using Docker for Verifiable Solana Builds
Verifiable Solana Builds of Native Solana programs with Docker.
What are Verifiable Solana Builds?
Here's a great paragraph on Anchor Lang documentation that quickly sums up the importance of having Verifiable Solana Builds:
Building programs with the Solana CLI may embed machine specific code into the resulting binary. As a result, building the same program on different machines may produce different executables. To get around this problem, one can build inside a docker image with pinned dependencies to produce a verifiable build.
When do verifiable Solana builds matter the most?
This matters a lot to the community that supports you by confirming if what is deployed onchain is equivalent to what you published as Opensource.
By deploying a Verifiable Solana Build, you empower your community with the capacity to audit your integrity as a project owner.
Hence if you're planning to deploy a Solana program any time soon, choose to deploy a verifiable build!
How to create a Verifiable Solana Build?
There are 3 main steps you need to do in creating a Verifiable Solana Build.
- Identify the pinned versions of Rust, Solana CLI, and Anchor you will use for your Docker image.
- Build the Docker image you will be using for creating a Verifiable Solana Builder with a
Dockerfile
- Build your program using your image.
To simplify this process, this guide comes with a supplementary Github repository you can use as a reference.
This repository comes with:
- A
CounterTest
Native Solana program you will build using your Docker image - A
Dockerfile
you will use to build your image. - A
build.sh
executable file you can use to start building your Solana program using your Docker image.
Identify pinned versions of Rust and Solana CLI
For this guide, you will only be compiling a Native Solana program hence will only need a pinned version of Rust and Solana CLI:
Build your Docker image with a Dockerfile
Here's the multi-stage Dockerfile
you'll be using to build your Native Solana program.
# Build Image
ARG RUST_IMAGE_TAG=1.79
FROM --platform=linux/amd64 rust:${RUST_IMAGE_TAG} as builder
ARG SOLANA_CLI=v1.18.16
# Install Solana CLI
RUN curl -sSfL "https://release.solana.com/${SOLANA_CLI}/install" | sh
# Make sure Solana PATH is added to environment
ENV PATH="/root/.local/share/solana/install/active_release/bin:${PATH}"
# Usage image to build
FROM --platform=linux/amd64 builder
COPY . .
CMD ["cargo", "build-sbf"]
Let's unpack this Dockerfile
step by step.
This section defines the base image and establishes the pinned versions of Rust and Solana CLI.
# Build Image
ARG RUST_IMAGE_TAG=1.79
FROM --platform=linux/amd64 rust:${RUST_IMAGE_TAG} as builder
ARG SOLANA_CLI=v1.18.16
This section installs the Solana CLI tool and ensures that it persists in the image's PATH
environment variable.
# Install Solana CLI
RUN curl -sSfL "https://release.solana.com/${SOLANA_CLI}/install" | sh
# Make sure Solana PATH is added to environment
ENV PATH="/root/.local/share/solana/install/active_release/bin:${PATH}"
This section focuses on the 2nd stage of the build and utilizes the previously built image named as builder
. It also copies the files from host
to container
and ends with a cargo build-sbf
command to build your Native Solana program.
# Usage image to build
FROM --platform=linux/amd64 builder
COPY . .
CMD ["cargo", "build-sbf"]
Build your program with build.sh
After identifying your pinned versions and building your Dockerfile
, it's time to build your program.
This is the build.sh
script responsible for:
- Building your image with
docker build
- Running your image with
docker run
- Mounting volumes to synchronous data from container to host with
docker run
's-v
option.
#!/bin/bash
# get repo root for reference point
REPO_ROOT=$(git rev-parse --show-toplevel)
pushd $REPO_ROOT
# configuration
RUST_IMAGE_TAG=1.79
SOLANA_CLI=v1.18.16
# separate folder form target/ to prevent Permission Denied error
HOST_FOLDER_ABSOLUTE_PATH=$REPO_ROOT/verified
CONTAINER_FOLDER_ABSOLUTE_PATH=/target
IMAGE_NAME=verifiable-solana-build
docker build --build-arg "RUST_IMAGE_TAG=$RUST_IMAGE_TAG" --build-arg "SOLANA_CLI=$SOLANA_CLI" -t $IMAGE_NAME .
docker run --rm --name "build-$IMAGE_NAME" -v $HOST_FOLDER_ABSOLUTE_PATH:$CONTAINER_FOLDER_ABSOLUTE_PATH $IMAGE_NAME
popd
The key part of this build script is to make sure that you run (docker run
) your image with mounted volumes else your build won't persist in your host device.
In this build script, you sync the files in the container at /target
directory to your host machine's ./verified
folder inside the repository.
Start building your Verifiable Solana Build!
Change the directory into the root of the supplementary repository, run ./build.sh
, and WAIT!
After waiting for the compilation to end, if there are no errors you should be left with a /verifiable
folder in your repository containing your artifacts like below.
Conclusion
Deploying a Verifiable Solana Build enables you to build trust by empowering your community to audit your integrity.
Do you find this guide helpful? There's more!