Expressif can be built and executed as a Docker image. This allows you to use the Expressif CLI without installing Expressif or the .NET runtime directly on your machine.
The general workflow is:
Download and extract the container archive
↓
Build an Ubuntu or Alpine image
↓
Run Expressif commands through Docker
Container archive
The Expressif container archive contains the files required to build Docker images locally.
Its content is similar to:
build-container.ps1
ubuntu/
└── Dockerfile
alpine/
└── Dockerfile
The archive contains:
- a PowerShell script named
build-container.ps1; - a Dockerfile for Ubuntu;
- a Dockerfile for Alpine.
The archive does not contain prebuilt Docker images.
Instead, it contains the manifests required to build images containing the latest available version of Expressif.
How the Expressif version is selected
The Dockerfiles do not target the Expressif version associated with the container archive itself.
When you build an image, the Dockerfile looks up and downloads the latest available Expressif release at that moment.
This means that the Expressif version is selected at image build time.
Run build-container.ps1
↓
The latest Expressif release is resolved
↓
Expressif is downloaded into the image
↓
The resulting image contains that fixed version
You do not necessarily need to download a newer container archive when a new Expressif version is released.
Re-running build-container.ps1 is sufficient to retrieve the latest Expressif version, provided that the existing Dockerfiles remain compatible with the current Expressif release format.
Expressif versions are fixed inside built images
Once an image has been built, the version of Expressif contained in that image is fixed.
Running the image does not check whether a newer Expressif release exists.
Starting a new container from the same image also does not update Expressif. Every container created from that image uses the same embedded version.
To use a newer Expressif version, rebuild the image by running build-container.ps1 again.
Existing image
└── Expressif version remains unchanged
Run build-container.ps1 again
└── A new image is built with the latest available version
Prerequisites
Before building the images, ensure that Docker and PowerShell are available.
You can verify Docker with:
docker --version
You can verify PowerShell with:
pwsh --version
On Windows, Docker Desktop must be running before executing the build script.
Extract the archive
Extract the container archive into a directory of your choice.
For example:
Expressif-containers/
├── build-container.ps1
├── ubuntu/
│ └── Dockerfile
└── alpine/
└── Dockerfile
Open PowerShell and move into the extracted directory:
Set-Location .\Expressif-containers
Build the Ubuntu image
Run:
.\build-container.ps1 ubuntu
The script builds an Ubuntu-based Docker image and tags it as:
expressif:ubuntu
The build downloads the latest available Expressif release and installs it into the image.
Build the Alpine image
Run:
.\build-container.ps1 alpine
The script builds an Alpine-based Docker image and tags it as:
expressif:alpine
Alpine images are generally smaller, while Ubuntu images may be easier to inspect or troubleshoot and may offer broader compatibility with native dependencies.
For normal Expressif CLI usage, either variant can be used.
Verify the built images
List the available Expressif images with:
docker image ls expressif
The output should contain one or both of the following tags:
expressif:ubuntu
expressif:alpine
You can verify the Expressif version embedded in the Ubuntu image with:
docker run --rm expressif:ubuntu version
For Alpine:
docker run --rm expressif:alpine version
Run Expressif
Arguments placed after the image name are passed directly to the Expressif CLI.
The general syntax is:
docker run --rm expressif:<variant> <command> [arguments]
For example:
docker run --rm expressif:ubuntu version
docker run --rm expressif:ubuntu evaluate "absolute | add(3)" input "-5"
docker run --rm expressif:ubuntu validate "absolute | add(3)" input "-5"
The same commands can be run with the Alpine image:
docker run --rm expressif:alpine evaluate "absolute | add(3)" input "-5"
Display the Expressif help
Run:
docker run --rm expressif:ubuntu --help
You can also display help for a specific command:
docker run --rm expressif:ubuntu evaluate --help
What happens when no command is provided
Running the image without an Expressif command:
docker run --rm expressif:ubuntu
starts the Expressif CLI, but no command is passed to it.
Expressif therefore displays its usage information and reports that a command is required.
For example:
Required command was not provided.
Description:
Evaluate and validate Expressif expressions.
Usage:
Expressif.Cli [command] [options]
This does not indicate a problem with the image. It confirms that the Expressif executable was started successfully.
Container lifecycle
Expressif is a command-line application, not a continuously running service.
When you execute:
docker run --rm expressif:ubuntu version
Docker performs the following operations:
- A new container is created from the
expressif:ubuntuimage. - The Expressif
versioncommand is executed. - The command produces its output.
- The container stops.
- The stopped container is deleted because
--rmwas specified.
The Docker image itself is not deleted. It remains available for subsequent commands.
Each new docker run command creates a new short-lived container from the same image.
Purpose of --rm
The --rm option tells Docker to delete the container after the Expressif command completes.
For example:
docker run --rm expressif:ubuntu version
Without --rm:
docker run expressif:ubuntu version
the container still stops when the command completes, but the stopped container remains stored by Docker.
Stopped containers can be listed with:
docker ps -a
Because Expressif commands are normally stateless, using --rm is recommended.
Rebuild an image to update Expressif
To update the Ubuntu image to the latest available Expressif release, run:
.\build-container.ps1 ubuntu
To update the Alpine image:
.\build-container.ps1 alpine
The build script forces Docker to rebuild the image and retrieve the latest Expressif release instead of reusing a previously downloaded release.
After rebuilding, confirm the embedded version with:
docker run --rm expressif:ubuntu version
You do not need to download a newer container archive for every Expressif release.
A newer archive is only required when the container definitions or build process themselves have changed, or when the existing Dockerfiles are no longer compatible with the Expressif release format.
Image tags and rebuilds
The build script uses a stable tag for each variant:
expressif:ubuntu
expressif:alpine
When the image is rebuilt, the tag is assigned to the newly built image.
Consequently:
docker run --rm expressif:ubuntu version
uses the most recently built Ubuntu image carrying that tag.
Existing containers created from an older image are not updated. However, this is normally irrelevant when using --rm, because those containers are removed immediately after execution.
Choosing between Ubuntu and Alpine
Use Ubuntu when:
- you prefer a familiar Linux environment;
- you want easier interactive troubleshooting;
- you expect to add tools or native dependencies to the image.
Use Alpine when:
- image size is a priority;
- you want a minimal runtime environment;
- your usage is limited to running the Expressif CLI.
Both images expose the same Expressif commands.
Complete example
The following example extracts the archive, builds the Ubuntu image, verifies its version, and evaluates an expression:
Expand-Archive `
-Path .\Expressif-containers.zip `
-DestinationPath .\Expressif-containers
Set-Location .\Expressif-containers
.\build-container.ps1 ubuntu
docker run --rm expressif:ubuntu version
docker run --rm expressif:ubuntu evaluate "absolute | add(3)" input "-5"
To use Alpine instead:
.\build-container.ps1 alpine
docker run --rm expressif:alpine version
docker run --rm expressif:alpine evaluate "absolute | add(3)" input "-5"
Troubleshooting
Docker is not running
If Docker cannot connect to the Docker daemon, ensure that Docker Desktop or Docker Engine is running.
You can test Docker with:
docker info
The build script cannot be executed
PowerShell may block scripts downloaded from the internet.
You can unblock the script with:
Unblock-File .\build-container.ps1
Then run it again:
.\build-container.ps1 ubuntu
The image cannot be found
An error such as:
Unable to find image 'expressif:ubuntu' locally
usually means that the image has not yet been built or that the expected tag was not created.
Build it with:
.\build-container.ps1 ubuntu
Then verify it with:
docker image ls expressif
The image still contains an older Expressif version
Rebuild the image:
.\build-container.ps1 ubuntu
Then check the version again:
docker run --rm expressif:ubuntu version
Also verify that the existing container definition is still compatible with the current structure of Expressif GitHub releases.
No Expressif command was provided
This command:
docker run --rm expressif:ubuntu
starts Expressif without arguments.
Provide a command such as:
docker run --rm expressif:ubuntu version
or:
docker run --rm expressif:ubuntu evaluate "absolute | add(3)" input "-5"