> We recommend that, the frontend and the backend communicate through sockets, and named pipes on Windows, instead of
> HTTP. This prevents port collision with any other running application or container running
> on the host. Also, some Docker Desktop users are running in constrained environments where they
> can't open ports on their machines. When choosing the language and framework for your backend, make sure it
> supports sockets connection.
{{< tabs group="lang" >}}
{{< tab name="Go" >}}
```go
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
}
```
{{< /tab >}}
{{< tab name="Node" >}}
> [!IMPORTANT]
>
> We don't have a working example for Node yet. [Fill out the form](https://docs.google.com/forms/d/e/1FAIpQLSdxJDGFJl5oJ06rG7uqtw1rsSBZpUhv_s9HHtw80cytkh2X-Q/viewform?usp=pp_url&entry.25798127=Node)
> and let us know if you'd like a sample for Node.
{{< /tab >}}
{{< tab name="Python" >}}
> [!IMPORTANT]
>
> We don't have a working example for Python yet. [Fill out the form](https://docs.google.com/forms/d/e/1FAIpQLSdxJDGFJl5oJ06rG7uqtw1rsSBZpUhv_s9HHtw80cytkh2X-Q/viewform?usp=pp_url&entry.25798127=Python)
> and let us know if you'd like a sample for Python.
{{< /tab >}}
{{< tab name="Java" >}}
> [!IMPORTANT]
>
> We don't have a working example for Java yet. [Fill out the form](https://docs.google.com/forms/d/e/1FAIpQLSdxJDGFJl5oJ06rG7uqtw1rsSBZpUhv_s9HHtw80cytkh2X-Q/viewform?usp=pp_url&entry.25798127=Java)
> and let us know if you'd like a sample for Java.
{{< /tab >}}
{{< tab name=".NET" >}}
> [!IMPORTANT]
>
> We don't have a working example for .NET. [Fill out the form](https://docs.google.com/forms/d/e/1FAIpQLSdxJDGFJl5oJ06rG7uqtw1rsSBZpUhv_s9HHtw80cytkh2X-Q/viewform?usp=pp_url&entry.25798127=.Net)
> and let us know if you'd like a sample for .NET.
{{< /tab >}}
{{< /tabs >}}
## Adapt the Dockerfile
> [!NOTE]
>
> When using the `docker extension init`, it creates a `Dockerfile` that already contains what is needed for a Go backend.
{{< tabs group="lang" >}}
{{< tab name="Go" >}}
To deploy your Go backend when installing the extension, you need first to configure the `Dockerfile`, so that it:
- Builds the backend application
- Copies the binary in the extension's container filesystem
- Starts the binary when the container starts listening on the extension socket
> [!TIP]
>
> To ease version management, you can reuse the same image to build the frontend, build the
backend service, and package the extension.
```dockerfile
# 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
```
{{< /tab >}}
{{< tab name="Node" >}}