为你的扩展添加后端
你的扩展可以包含后端部分,前端可以与其交互。本页面提供关于为什么以及如何添加后端的信息。
开始之前,请确保你已安装最新版本的 Docker Desktop。
提示
查阅快速入门指南和
docker extension init <my-extension>
。它们为你的扩展提供了一个更好的基础,因为它们是最新的并且与你安装的 Docker Desktop 相关。
为什么添加后端?
借助 Docker Extensions SDK,大多数情况下,你可以直接从前端执行 Docker CLI 中的大部分操作。
尽管如此,在某些情况下,你可能需要为扩展添加后端。到目前为止,扩展开发者已经使用后端来:
- 将数据存储在本地数据库中并通过 REST API 提供服务。
- 存储扩展状态,例如当一个按钮启动一个长时间运行的进程时,这样即使你离开了扩展用户界面再返回,前端也能接着之前的地方继续。
有关扩展后端的更多信息,请参阅架构。
为扩展添加后端
如果你使用 docker extension init
命令创建了扩展,则已经设置好了后端。否则,你需要先创建一个包含代码的 vm
目录,并更新 Dockerfile 以将其容器化。
这是一个带有后端的扩展文件夹结构
.
├── Dockerfile # (1)
├── Makefile
├── metadata.json
├── ui
└── index.html
└── vm # (2)
├── go.mod
└── main.go
- 包含构建后端并将其复制到扩展容器文件系统中的所有必需内容。
- 包含扩展后端代码的源文件夹。
尽管你可以从一个空目录或从 vm-ui 扩展示例开始,但强烈建议你从 docker extension init
命令开始并根据你的需要进行修改。
提示
docker extension init
命令会生成一个 Go 后端。但你仍可以将其作为你自己扩展的起点,并使用其他任何语言,如 Node.js、Python、Java、.Net 或任何其他语言和框架。
在本教程中,后端服务只暴露一个路由,该路由返回一个 JSON 有效载荷,其中包含“Hello”。
{ "Message": "Hello" }
重要
我们建议前端和后端通过 socket 进行通信(在 Windows 上使用命名管道),而不是 HTTP。这可以防止与主机上运行的任何其他应用程序或容器发生端口冲突。此外,一些 Docker Desktop 用户在受限环境中运行,无法在其机器上打开端口。在为后端选择语言和框架时,请确保它支持 socket 连接。
package main
import (
"flag"
"log"
"net"
"net/http"
"os"
"github.com/labstack/echo"
"github.com/sirupsen/logrus"
)
func main() {
var socketPath string
flag.StringVar(&socketPath, "socket", "/run/guest/volumes-service.sock", "Unix domain socket to listen on")
flag.Parse()
os.RemoveAll(socketPath)
logrus.New().Infof("Starting listening on %s\n", socketPath)
router := echo.New()
router.HideBanner = true
startURL := ""
ln, err := listen(socketPath)
if err != nil {
log.Fatal(err)
}
router.Listener = ln
router.GET("/hello", hello)
log.Fatal(router.Start(startURL))
}
func listen(path string) (net.Listener, error) {
return net.Listen("unix", path)
}
func hello(ctx echo.Context) error {
return ctx.JSON(http.StatusOK, HTTPMessageBody{Message: "hello world"})
}
type HTTPMessageBody struct {
Message string
}
重要
我们目前还没有 Node 的可用示例。填写表格,告诉我们你是否需要 Node 的示例。
重要
我们目前还没有 Python 的可用示例。填写表格,告诉我们你是否需要 Python 的示例。
重要
我们目前还没有 Java 的可用示例。填写表格,告诉我们你是否需要 Java 的示例。
重要
我们目前还没有 .NET 的可用示例。填写表格,告诉我们你是否需要 .NET 的示例。
修改 Dockerfile
注意
使用
docker extension init
命令时,它会创建一个 Dockerfile,其中已包含 Go 后端所需的内容。
要在安装扩展时部署你的 Go 后端,你需要先配置 Dockerfile,以便它能:
- 构建后端应用程序
- 将二进制文件复制到扩展的容器文件系统中
- 当容器启动并监听扩展 socket 时启动该二进制文件
提示
为了方便版本管理,你可以重用同一个镜像来构建前端、构建后端服务和打包扩展。
# syntax=docker/dockerfile:1
FROM node:17.7-alpine3.14 AS client-builder
# ... build frontend application
# Build the Go backend
FROM golang:1.17-alpine AS builder
ENV CGO_ENABLED=0
WORKDIR /backend
COPY vm/go.* .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
COPY vm/. .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go build -trimpath -ldflags="-s -w" -o bin/service
FROM alpine:3.15
# ... add labels and copy the frontend application
COPY --from=builder /backend/bin/service /
CMD /service -socket /run/guest-services/extension-allthethings-extension.sock
重要
我们目前还没有 Node 的可用 Dockerfile。填写表格,告诉我们你是否需要 Node 的 Dockerfile。
重要
我们目前还没有 Python 的可用 Dockerfile。填写表格,告诉我们你是否需要 Python 的 Dockerfile。
重要
我们目前还没有 Java 的可用 Dockerfile。填写表格,告诉我们你是否需要 Java 的 Dockerfile。
重要
我们目前还没有 .Net 的可用 Dockerfile。填写表格,告诉我们你是否需要 .Net 的 Dockerfile。
配置元数据文件
要在 Docker Desktop 的 VM 内部启动扩展的后端服务,你必须在 metadata.json
文件的 vm
部分配置镜像名称。
{
"vm": {
"image": "${DESKTOP_PLUGIN_IMAGE}"
},
"icon": "docker.svg",
"ui": {
...
}
}
有关 metadata.json
文件中 vm
部分的更多信息,请参阅元数据。
警告
请勿替换
metadata.json
文件中的${DESKTOP_PLUGIN_IMAGE}
占位符。安装扩展时,该占位符将自动替换为正确的镜像名称。
从前端调用扩展后端
使用高级前端扩展示例,我们可以调用我们的扩展后端。
使用 Docker Desktop Client 对象,然后使用 ddClient. extension.vm.service.get
从后端服务调用 /hello
路由,该方法返回响应体。
将 ui/src/App.tsx
文件替换为以下代码
// ui/src/App.tsx
import React, { useEffect } from 'react';
import { createDockerDesktopClient } from "@docker/extension-api-client";
//obtain docker desktop extension client
const ddClient = createDockerDesktopClient();
export function App() {
const ddClient = createDockerDesktopClient();
const [hello, setHello] = useState<string>();
useEffect(() => {
const getHello = async () => {
const result = await ddClient.extension.vm?.service?.get('/hello');
setHello(JSON.stringify(result));
}
getHello()
}, []);
return (
<Typography>{hello}</Typography>
);
}
重要
我们目前还没有 Vue 的示例。填写表格,告诉我们你是否需要 Vue 的示例。
重要
我们还没有 Angular 的示例。填写表单,并告诉我们您是否需要 Angular 示例。
重要
我们还没有 Svelte 的示例。填写表单,并告诉我们您是否需要 Svelte 示例。
重新构建并更新扩展
由于您修改了扩展的配置并在 Dockerfile 中添加了一个阶段,您必须重新构建扩展。
docker build --tag=awesome-inc/my-extension:latest .
构建完成后,您需要更新它,如果尚未安装,则安装它。
docker extension update awesome-inc/my-extension:latest
现在您可以在 Docker Desktop Dashboard 的 Containers 视图中看到后端服务正在运行,并在需要调试时查看日志。
提示
您可能需要开启 Settings 中的 Show system containers 选项,以查看后端容器正在运行。有关详细信息,请参阅 Show extension containers。
打开 Docker Desktop Dashboard 并选择 Containers 选项卡。您应该会看到后端服务调用的响应显示出来。