|
| 1 | +This tutorial describes a minimal example running frontend extension and invoking docker CLI commands. |
| 2 | + |
| 3 | +## Prerequisites |
| 4 | + |
| 5 | +- [Docker Desktop build with Extensions capabilities](https://github.com/docker/desktop-extension-samples/releases/) |
| 6 | +- [Docker Extensions CLI](https://github.com/docker/desktop-extension-samples/releases/) |
| 7 | + |
| 8 | +## Extension folder structure |
| 9 | + |
| 10 | +A Desktop Extension is comprised of several files, ranging from the extension's source code to required Extension-specific files. |
| 11 | + |
| 12 | +In the `minimal-docker-cli` folder, at the root of the repository, you can find a ready-to-go example that represents a UI Extension invoking docker commands. We will go through this code example in this tutorial. |
| 13 | + |
| 14 | +```bash |
| 15 | +. |
| 16 | +├── Dockerfile # (1) |
| 17 | +├── metadata.json # (2) |
| 18 | +└── ui # (3) |
| 19 | + ├── index.html |
| 20 | + └── script.js |
| 21 | +``` |
| 22 | + |
| 23 | +1. Contains everything required to build the extension and run it in Docker Desktop. |
| 24 | +2. A file that provides information about the extension such as the name, description, and version, among others. |
| 25 | +3. The source folder that contains all your HTML, CSS and JS files. These can also be other static assets like logos, icons, etc. |
| 26 | + |
| 27 | +## The extension's Dockerfile |
| 28 | + |
| 29 | +An extension requires a `Dockerfile` to build, publish and run in Docker Desktop. |
| 30 | + |
| 31 | +The bare minimum configuration that a Dockerfile's extension requires to function properly is: |
| 32 | + |
| 33 | +- Labels - required to provide extra information about the extension. |
| 34 | +- The source code - in this case, an `index.html` that sits within the `ui` folder. `index.html` refers to javascript code in `script.js`. |
| 35 | +- The `metadata.json` file. |
| 36 | + |
| 37 | +```Dockerfile title="Dockerfile" linenums="1" |
| 38 | +FROM scratch |
| 39 | + |
| 40 | +LABEL org.opencontainers.image.title="MyExtension" \ |
| 41 | + org.opencontainers.image.description="A sample extension to show how easy it's to get started with Desktop Extensions." \ |
| 42 | + org.opencontainers.image.vendor="Docker Inc." \ |
| 43 | + com.docker.desktop.extension.api.version="1.0.0-beta.1" |
| 44 | + |
| 45 | +COPY ui ./ui |
| 46 | +COPY metadata.json . |
| 47 | +``` |
| 48 | + |
| 49 | +## Configure the Extension metadata file |
| 50 | + |
| 51 | +A `metadata.json` file is required at the root of the image filesystem. |
| 52 | + |
| 53 | +```json title="metadata.json" linenums="1" |
| 54 | +{ |
| 55 | + "desktop-plugin-version": "1.0.0-beta.1", |
| 56 | + "name": "MyExtension", |
| 57 | + "provider": "Docker Inc.", |
| 58 | + "ui": { |
| 59 | + "dashboard-tab": { |
| 60 | + "title": "My Extension", |
| 61 | + "root": "/ui", |
| 62 | + "src": "index.html" |
| 63 | + } |
| 64 | + } |
| 65 | +} |
| 66 | +``` |
| 67 | + |
| 68 | +## Invoke docker CLI in your javascript code |
| 69 | + |
| 70 | +A `script.js` includes code that is executed when the extension tab is shown. |
| 71 | + |
| 72 | +In Javascript, extensions can use `windows.ddClient` to get access to the Docker Desktop extension API. |
| 73 | + |
| 74 | +On this ddClient object we can invoke `ddClient.ExecDockerCmd("sytem", "df", "--format", "'{{ json . }}'")`, and then use `res.parseJsonLines()` to read results as json objects. |
| 75 | + |
| 76 | +The rest is purely formatting code using the output of the Docker command: |
| 77 | + |
| 78 | +```javascript |
| 79 | +window.ddClient |
| 80 | + .execDockerCmd("system", "df", "--format", "'{{ json . }}'") |
| 81 | + .then((res) => { |
| 82 | + document.getElementById("size-info").innerHTML = ` |
| 83 | + <table> |
| 84 | + <tr> <th>Type</th> <th>Active</th> <th>Total</th> <th>Size</th> <th>Reclaimable</th> </tr> |
| 85 | + ${res |
| 86 | + .parseJsonLines() |
| 87 | + .map( |
| 88 | + (cat) => |
| 89 | + `<tr> <td>${cat.Type}</td> <td>${cat.Active}</td> <td>${cat.TotalCount}</td> <td>${cat.Size}</td> <td>${cat.Reclaimable}</td> </tr>` |
| 90 | + ) |
| 91 | + .join("")} |
| 92 | + </table> |
| 93 | +`; |
| 94 | + }); |
| 95 | +``` |
| 96 | + |
| 97 | +## Build the extension |
| 98 | + |
| 99 | +```bash |
| 100 | +docker build -t desktop-docker-cli-minimal-extension:0.0.1 . |
| 101 | +``` |
| 102 | + |
| 103 | +### Build the extension for multiple platforms |
| 104 | + |
| 105 | +```bash |
| 106 | +docker buildx build --platform=linux/amd64,linux/arm64 -t desktop-docker-cli-minimal-extension:0.0.1 . |
| 107 | +``` |
| 108 | + |
| 109 | +## Validate the extension |
| 110 | + |
| 111 | +Next, verify the extension image complies with the requisites to be a compliant Desktop Extension. |
| 112 | + |
| 113 | +The validation will check if the extension's `Dockerfile` specifies all the required labels and if the metadata file is valid against the JSON schema file. |
| 114 | + |
| 115 | +```bash |
| 116 | +docker extension validate desktop-docker-cli-minimal-extension:0.0.1 |
| 117 | +``` |
| 118 | + |
| 119 | +If your extension is valid, you should see the following message: |
| 120 | + |
| 121 | +`The extension image "desktop-docker-cli-minimal-extension:0.0.1" is valid`. |
| 122 | + |
| 123 | +## Install the extension |
| 124 | + |
| 125 | +Now that the extension is packaged as a Docker image, let's proceed with the installation. To do so, we'll use the Docker Extensions CLI. |
| 126 | + |
| 127 | +!!! info "Enable Docker Desktop Extensions" |
| 128 | + |
| 129 | + Ensure the Extensions capabilities are enabled in the Docker Desktop build by running `docker extension enable` |
| 130 | + |
| 131 | +To install the extension in Docker Desktop, run: |
| 132 | + |
| 133 | +```bash |
| 134 | +docker extension install desktop-docker-cli-minimal-extension:0.0.1 |
| 135 | +``` |
| 136 | + |
| 137 | +If the installation was successful, you should see the following output: |
| 138 | + |
| 139 | +```bash |
| 140 | +Installing new extension "MyExtension" with desktop-docker-cli-minimal-extension:0.0.1 ... |
| 141 | +Installing Desktop extension UI for tab "My Extension"... |
| 142 | +Extension UI tab "Disk usage" added. |
| 143 | +Extension "MyExtension" installed successfully |
| 144 | +``` |
| 145 | + |
| 146 | +## Preview the extension |
| 147 | + |
| 148 | +You can verify that the extension has been installed successfully using the following CLI command: |
| 149 | + |
| 150 | +```bash |
| 151 | +docker extension ls |
| 152 | +``` |
| 153 | + |
| 154 | +It outputs all the extensions installed: |
| 155 | + |
| 156 | +```bash |
| 157 | +PLUGIN PROVIDER IMAGE UI VM HOST |
| 158 | +MyExtension Docker Inc. desktop-docker-cli-minimal-extension:0.0.1 1 tab(My Extension) - - |
| 159 | +``` |
| 160 | + |
| 161 | +To preview the extension in Docker Desktop, close and open the Docker Desktop Dashboard once the installation has completed. |
| 162 | + |
| 163 | +On the left menu, you should see a new tab with the name `Disk usage`. Click on it to load the main window that will run the javascript code, invoke the `docker system df` command, and render the results. |
| 164 | + |
| 165 | + |
| 166 | + |
| 167 | +## Publish the extension |
| 168 | + |
| 169 | +In order to publish the extension, we have to upload the Docker image to [DockerHub](https://hub.docker.com). |
| 170 | + |
| 171 | +Let's tag the previous image to preprend the account owner at the beginning of the image name: |
| 172 | + |
| 173 | +```bash |
| 174 | +docker tag desktop-docker-cli-minimal-extension:0.0.1 owner/desktop-docker-cli-minimal-extension:0.0.1 |
| 175 | +``` |
| 176 | + |
| 177 | +```bash |
| 178 | +docker push owner/desktop-docker-cli-minimal-extension:0.0.1 |
| 179 | +``` |
| 180 | + |
| 181 | +!!! warning |
| 182 | + |
| 183 | + Note that for Docker Extensions images to be listed in Docker Desktop, they must be approved by Docker and be tagged following semantic versioning, e.g: `0.0.1`. |
| 184 | + |
| 185 | + See [distribution and new releases](../extensions/DISTRIBUTION.md#distribution-and-new-releases) for more information. |
| 186 | + |
| 187 | + See <a href="https://semver.org/" target="__blank">semver.org</a> to learn more about semantic versioning. |
| 188 | + |
| 189 | +!!! info "Having trouble to push the image?" |
| 190 | + |
| 191 | + Ensure you are logged into DockerHub. Otherwise, run `docker login` to authenticate. |
| 192 | + |
| 193 | +## Clean up |
| 194 | + |
| 195 | +```bash |
| 196 | +docker extension rm desktop-docker-cli-minimal-extension |
| 197 | +``` |
| 198 | + |
| 199 | +The following output should be displayed: |
| 200 | + |
| 201 | +```bash |
| 202 | +Removing extension MyExtension... |
| 203 | +Extension UI tab Disk usage removed |
| 204 | +Extension "MyExtension" removed |
| 205 | +``` |
| 206 | + |
| 207 | +## What's next? |
| 208 | + |
| 209 | +See the next [tutorial](../minimal-backend-extension) to create a minimal backend extension. |
0 commit comments