# Build your first Docker Extension

**TABLE OF CONTENTS :**

* Introduction to Docker Extensions.
    
* Prerequisites.
    
* Getting Started.
    
* Building the Extension.
    
* Installing the Extension in the Docker Desktop.
    
* Updating and Rebuilding the Extension.
    
* Open Chrome Dev Tools.
    
* Validate your Extension.
    
* Build the extensions for multiple architectures.
    

## Introduction:

What are Docker Extensions?

* Docker Extensions are a way to add new functionality to the Docker Desktop Application.
    
* Developers can easily integrate their preferred development tools into their application development and deployment workflows via extensions.
    
* Communities, Partners, and Individuals can contribute to Docker Desktop by building and publishing their extensions.
    
* It is a way to discover new tools to solve existing problems.
    

## Prerequisites:

To follow along with this tutorial, you'll need

* The [latest version](https://www.docker.com/products/docker-desktop/) of Docker Desktop.
    

Install the latest version of Docker Desktop.

## Getting Started!!

**Create the extension file**

Type the following command in your CLI to create an extension file.

```plaintext
docker extension init my_extension
```

A few questions to set up your "my\_extension" directory will be asked as you start with this command in your CLI.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681060932693/e557cf80-b9c9-42ad-b36c-d00e9ecc5d74.png align="center")

```plaintext
cd my_extension
```

**You should be able to see these files in your directory ( I have opened the directory in my VS Code ) recommend you do the same.**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681061427335/44621680-f91e-4e0c-81df-e76ff149a236.png align="center")

Here, the `ui` folder contains a react application and the `backend` folder contains a Go backend service for the application.

`Makefile` helps you run things locally, ensuring that the environment is exactly what it will be when you run it on your servers. On top of that, it removes the need to install every tool locally and instead allows you to simply run a docker command to have your application running.

`Dockerfile` is a text file of instructions that are used **to automate the** installation and configuration of a Docker image.

`Docker Compose.yaml` is used for **running multiple containers as a single service**. Each of the containers here runs in isolation but can interact with each other when required. With Compose, you use a **YAML file** to configure your application's services.

`metadata.json` contains information about the extension.

## Building the Extension

A docker extension is the Docker image, so first let's try to build the extension image.

```plaintext
docker build -t my/docker-extension:latest .
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681064722096/22ed1388-8d34-41a8-9c71-dcb1c56114ad.png align="center")

Three steps of a multi-stage Dockerfile are offered while building our extension :

The first builds the `backend service`, the second the `React app`, and the third copies the `backend binaries` and the `React components`. The backend service is then launched with the CMD command, which uses a socket to watch for requests from the React app.

**To build the extension, use either** `docker build` **or the preset** `make build-extension` **command.**

## Installing the Extension in the Docker Desktop

```plaintext
docker extension install my/docker-extension:latest
```

```plaintext
y
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681065256389/1ec8bc47-fe84-46cd-8daf-fd1e4cb7e96c.png align="center")

Open your Docker Desktop application, you'll be able to see your Extension named **My Extension** as well as the container for the Extension.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681065476146/c1402ffe-860c-4e0c-9394-f03b88be1bfa.png align="center")

Click on **My Extension**

Your very first Extension is ready. Hurraayy!!!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681065545180/9f1af8a3-f397-4715-8a2d-9a19800d0f70.png align="center")

Now click on the **Call backend** button and you'll be able to see the response from the Backend saying ''hello''.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681065702017/99b37fcf-b566-4775-93b4-108905fa2665.png align="center")

We can check that the extension has been installed using the following CLI command

```plaintext
docker extension ls
```

Output:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681068159937/3204def8-9ca7-482a-804b-29a50cdf6c6f.png align="center")

## Updating and Rebuilding the Extension

Let's make minor changes to our Code

In the **main.go** file, we have made the changes in our message from **"hello"** to **"hello, this is our First Extension!!!"**

Save the file.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681066159333/88074aa5-20d1-4461-b5ed-70638bce31f9.png align="center")

In the **App.tsx** file,

We have added an Extension UI API (The extension UI API provides a way for the frontend to perform different actions and communicate with the Docker Desktop dashboard or the underlying system.)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681066544554/207e511d-b47b-47e3-bc85-95740f074636.png align="center")

Toasts provide a brief notification to the user. They appear temporarily and shouldn’t interrupt the user experience. They also don’t require user input to disappear.

The **Success!!!** message will be displayed on the Docker Desktop Dashboard.

Visit [https://docs.docker.com/desktop/extensions-sdk/dev/api/dashboard/](https://docs.docker.com/desktop/extensions-sdk/dev/api/dashboard/) for more such toast messages.

Let's build our application again in order to affect the changes that we made in our code.

```plaintext
docker build -t my/docker-extension:latest .
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681067032779/6b78ad87-e210-4967-8330-dea55aed44b8.png align="center")

### NOTE: After building your application you cannot try to install it again with the same command you used to install your application for the first time as it will throw an error saying the application is already installed.

We need to update our extension :

```plaintext
docker extension update my/docker-extension:latest
```

```plaintext
y
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681067419961/1d660a9e-6e65-46f8-8c0a-bc9d95c51939.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681067602062/78cea00c-6f29-4f80-ba83-309266781cf8.png align="center")

Congrats!! We have successfully updated our Extension...

## **Open Chrome Dev Tools**

In order to open the Chrome Dev Tools for your extension when clicking on the extension tab, run:

`docker extension dev debug my/docker-extension:latest`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681068476053/5c874c0c-b7ce-467e-8407-f809741b3e8d.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681068491983/30262a9b-6899-4ec5-a2b6-243af68054be.png align="center")

In order to stop the debug mode, use the following command:

```plaintext
docker extension dev reset my/docker-extension:latest
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681068638078/591f6db2-145b-4daf-a5de-f96debe58cf0.png align="center")

## Validate your Extension

Validate your extension before you share or publish it. Validating the extension ensures:

* That the extension is built with the image labels it requires to display correctly in the marketplace
    
* That the extension installs and runs without problems
    
* The validation checks if the extension’s `Dockerfile` specifies all the required labels and if the metadata file is valid against the JSON schema file.
    

To validate your extension, run:

```plaintext
docker extension validate <name-of-your-extension>
```

If your extension is valid, you will receive the message as:

```plaintext
The extension image "name-of-your-extension" is valid
```

## **Build the extensions for multiple architectures**

**Docker Desktop retrieves the extension image according to the user’s system architecture.**

**If the extension does not provide an image that matches the user’s system architecture, Docker Desktop is not able to install the extension. As a result, users can’t run the extension in Docker Desktop**.

To build the extension for multiple architectures, use the following command

Here the username should be your **docker hub** username.

```plaintext
docker buildx build --push --platform linux/amd64,linux/arm64 --tag username/my-extension:0.0.1 .
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681114717882/e61c3066-2069-41da-a415-95a87115197a.png align="center")

**TAKE A LOOK AT THE ERROR MESSAGE...**

The issue is that the default driver for docker(which is named docker) does not support multi-architecture builds.

Multi-architecture images are images that can be used on **multiple platforms**. For example, images that can run on **Intel Macs(amd64)** and **M1 Macs (arm64)**. You will find this useful, as most users of your images would use them on various platforms.

To solve this create a new builder, using a different driver like `docker-container` which supports multi-architecture builds.

### STEPS FOR CREATING YOUR CUSTOM BUILDER

* Create your custom builder by running
    
    ```plaintext
    docker buildx create --name mycustombuilder --driver docker-container --bootstrap
    ```
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681115290661/6b1fd530-c5c3-4592-a5ab-171956eca910.png align="center")

* Ask docker to use this new builder for future builds by running
    
    ```plaintext
    docker buildx use mycustombuilder
    ```
    
* Inspect buildx to see if docker has indeed switched builders to the new one you asked it to use by running
    
    ```plaintext
    docker buildx inspect
    ```
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681115960153/66dfb591-2efc-4230-823d-109ba25fc551.png align="center")
    

Good! Now you can build extension for multiple architectures by running the following command

DO NOT FORGET TO SPECIFY YOUR DOCKER HUB **USERNAME**

```plaintext
docker buildx build --push --platform linux/amd64,linux/arm64 --tag username/my-extension:0.0.1 .
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681116591170/402b0b8f-6075-486c-ad34-79739d79ff96.png align="center")

Once the build is complete, go to your docker hub account and check the newly pushed image in your repository

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681116724538/ff512e25-a931-45c5-a86a-68ab0bf43194.png align="center")

Click on the Image which you pushed recently

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681116776103/becbb5eb-32e1-4cca-ac3b-597598185880.png align="center")

We can now see that the image supports multi-architecture..

**THANK YOU FOR READING...**
