1
0
mirror of https://github.com/artvs18/PostgreSQL-docker-image.git synced 2025-07-16 22:42:18 +02:00

Version 0.1

Version 0.1 of Docker PostgreSQL image
This commit is contained in:
Artemy Volkov
2023-01-28 01:35:53 +03:00
commit 7093744323
24 changed files with 11059 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

1
.dockerignore Normal file
View File

@ -0,0 +1 @@
ui/node_modules

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
ui/build

45
Dockerfile Normal file
View File

@ -0,0 +1,45 @@
FROM golang:1.19-alpine AS builder
ENV CGO_ENABLED=0
WORKDIR /backend
COPY backend/go.* .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
COPY backend/. .
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 --platform=$BUILDPLATFORM node:18.12-alpine3.16 AS client-builder
WORKDIR /ui
# cache packages in layer
COPY ui/package.json /ui/package.json
COPY ui/package-lock.json /ui/package-lock.json
RUN --mount=type=cache,target=/usr/src/app/.npm \
npm set cache /usr/src/app/.npm && \
npm ci
# install
COPY ui /ui
RUN npm run build
FROM alpine
LABEL org.opencontainers.image.title="PostgresSQL" \
org.opencontainers.image.description="This extension supports russian language and more!" \
org.opencontainers.image.vendor="artvs18" \
com.docker.desktop.extension.api.version="0.3.3" \
com.docker.extension.screenshots="" \
com.docker.extension.detailed-description="" \
com.docker.extension.publisher-url="" \
com.docker.extension.additional-urls="" \
com.docker.extension.changelog=""
COPY --from=builder /backend/bin/service /
COPY docker-compose.yaml .
COPY metadata.json .
COPY docker.svg .
COPY --from=client-builder /ui/build ui
CMD /service -socket /run/guest-services/backend.sock
FROM postgres:15.1
RUN localedef -i ru_RU -c -f UTF-8 -A /usr/share/locale/locale.alias ru_RU.UTF-8
ENV LANG ru_RU.utf8

28
Makefile Normal file
View File

@ -0,0 +1,28 @@
IMAGE?=artvs18/postgres
TAG?=latest
BUILDER=buildx-multi-arch
INFO_COLOR = \033[0;36m
NO_COLOR = \033[m
build-extension: ## Build service image to be deployed as a desktop extension
docker build --tag=$(IMAGE):$(TAG) .
install-extension: build-extension ## Install the extension
docker extension install $(IMAGE):$(TAG)
update-extension: build-extension ## Update the extension
docker extension update $(IMAGE):$(TAG)
prepare-buildx: ## Create buildx builder for multi-arch build, if not exists
docker buildx inspect $(BUILDER) || docker buildx create --name=$(BUILDER) --driver=docker-container --driver-opt=network=host
push-extension: prepare-buildx ## Build & Upload extension image to hub. Do not push if tag already exists: make push-extension tag=0.1
docker pull $(IMAGE):$(TAG) && echo "Failure: Tag already exists" || docker buildx build --push --builder=$(BUILDER) --platform=linux/amd64,linux/arm64 --build-arg TAG=$(TAG) --tag=$(IMAGE):$(TAG) .
help: ## Show this help
@echo Please specify a build target. The choices are:
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "$(INFO_COLOR)%-30s$(NO_COLOR) %s\n", $$1, $$2}'
.PHONY: help

107
README.md Normal file
View File

@ -0,0 +1,107 @@
# PostgresSQL
This repository defines an example of a Docker extension. The files in this repository have been automatically generated as a result of running `docker extension init`.
This extension is composed of:
- A [frontend](./ui) app in React that makes a request to the `/hello` endpoint and displays the payload in Docker Desktop.
- A [backend](./backend) container that runs an API in Go. It exposes the `/hello` endpoint which returns a JSON payload.
> You can build your Docker Extension using your fav tech stack:
>
> - Frontend: React, Angular, Vue, Svelte, etc.
> Basically, any frontend framework you can bundle in an `index.html` file with CSS, and JS assets.
> - Backend (optional): anything that can run in a container.
<details>
<summary>Looking for more templates?</summary>
1. [React + NodeJS](https://github.com/benja-M-1/node-backend-extension).
2. [React + .NET 6 WebAPI](https://github.com/felipecruz91/dotnet-api-docker-extension).
Request one or submit yours [here](https://github.com/docker/extensions-sdk/issues).
</details>
## Local development
You can use `docker` to build, install and push your extension. Also, we provide an opinionated [Makefile](Makefile) that could be convenient for you. There isn't a strong preference of using one over the other, so just use the one you're most comfortable with.
To build the extension, use `make build-extension` **or**:
```shell
docker buildx build -t artvs18/postgres:latest . --load
```
To install the extension, use `make install-extension` **or**:
```shell
docker extension install artvs18/postgres:latest
```
> If you want to automate this command, use the `-f` or `--force` flag to accept the warning message.
To preview the extension in Docker Desktop, open Docker Dashboard once the installation is complete. The left-hand menu displays a new tab with the name of your extension. You can also use `docker extension ls` to see that the extension has been installed successfully.
### Frontend development
During the development of the frontend part, it's helpful to use hot reloading to test your changes without rebuilding your entire extension. To do this, you can configure Docker Desktop to load your UI from a development server.
Assuming your app runs on the default port, start your UI app and then run:
```shell
cd ui
npm install
npm run dev
```
This starts a development server that listens on port `3000`.
You can now tell Docker Desktop to use this as the frontend source. In another terminal run:
```shell
docker extension dev ui-source artvs18/postgres:latest http://localhost:3000
```
In order to open the Chrome Dev Tools for your extension when you click on the extension tab, run:
```shell
docker extension dev debug artvs18/postgres:latest
```
Each subsequent click on the extension tab will also open Chrome Dev Tools. To stop this behaviour, run:
```shell
docker extension dev reset artvs18/postgres:latest
```
### Backend development (optional)
This example defines an API in Go that is deployed as a backend container when the extension is installed. This backend could be implemented in any language, as it runs inside a container. The extension frameworks provides connectivity from the extension UI to a socket that the backend has to connect to on the server side.
Note that an extension doesn't necessarily need a backend container, but in this example we include one for teaching purposes.
Whenever you make changes in the [backend](./backend) source code, you will need to compile them and re-deploy a new version of your backend container.
Use the `docker extension update` command to remove and re-install the extension automatically:
```shell
docker extension update artvs18/postgres:latest
```
> If you want to automate this command, use the `-f` or `--force` flag to accept the warning message.
> Extension containers are hidden from the Docker Dashboard by default. You can change this in Settings > Extensions > Show Docker Extensions system containers.
### Clean up
To remove the extension:
```shell
docker extension rm artvs18/postgres:latest
```
## What's next?
- To learn more about how to build your extension refer to the Extension SDK docs at https://docs.docker.com/desktop/extensions-sdk/.
- To publish your extension in the Marketplace visit https://www.docker.com/products/extensions/submissions/.
- To report issues and feedback visit https://github.com/docker/extensions-sdk/issues.
- To look for other ideas of new extensions, or propose new ideas of extensions you would like to see, visit https://github.com/docker/extension-ideas/discussions.

21
backend/go.mod Normal file
View File

@ -0,0 +1,21 @@
module postgres
go 1.19
require (
github.com/labstack/echo v3.3.10+incompatible
github.com/sirupsen/logrus v1.9.0
)
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
)

41
backend/go.sum Normal file
View File

@ -0,0 +1,41 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

62
backend/main.go Normal file
View File

@ -0,0 +1,62 @@
package main
import (
"flag"
"github.com/labstack/echo/middleware"
"net"
"net/http"
"os"
"github.com/labstack/echo"
"github.com/sirupsen/logrus"
)
var logger = logrus.New()
func main() {
var socketPath string
flag.StringVar(&socketPath, "socket", "/run/guest-services/backend.sock", "Unix domain socket to listen on")
flag.Parse()
_ = os.RemoveAll(socketPath)
logger.SetOutput(os.Stdout)
logMiddleware := middleware.LoggerWithConfig(middleware.LoggerConfig{
Skipper: middleware.DefaultSkipper,
Format: `{"time":"${time_rfc3339_nano}","id":"${id}",` +
`"method":"${method}","uri":"${uri}",` +
`"status":${status},"error":"${error}"` +
`}` + "\n",
CustomTimeFormat: "2006-01-02 15:04:05.00000",
Output: logger.Writer(),
})
logger.Infof("Starting listening on %s\n", socketPath)
router := echo.New()
router.HideBanner = true
router.Use(logMiddleware)
startURL := ""
ln, err := listen(socketPath)
if err != nil {
logger.Fatal(err)
}
router.Listener = ln
router.GET("/hello", hello)
logger.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"})
}
type HTTPMessageBody struct {
Message string
}

28
docker-compose.yaml Normal file
View File

@ -0,0 +1,28 @@
version: "1.0"
services:
postgres:
image: postgres:15.1
environment:
POSTGRES_DB: "postgres"
POSTGRES_USER: "admin"
POSTGRES_PASSWORD: "admin"
LC_COLLATE: 'ru_RU.UTF-8'
LC_CTYPE: 'ru_RU.UTF-8'
PGDATA: "/var/lib/postgresql/data/pgdata"
volumes:
- ../2. Init Database:/docker-entrypoint-initdb.d
- .:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin -d postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1'
memory: 4G

22
docker.svg Normal file
View File

@ -0,0 +1,22 @@
<svg viewBox="0 0 44 31" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M43.3876 11.6998C43.2688 11.6052 42.1585 10.78 39.819 10.78C39.2338 10.78 38.6164 10.8325 37.975 10.9363C37.523 7.87654 34.9606 6.38607 34.8414 6.31855L34.2127 5.96094L33.7983 6.54904C33.7674 6.5928 33.0393 7.6373 32.682 9.12402C32.2626 10.87 32.5171 12.5093 33.4173 13.9126C32.3302 14.5086 30.5949 14.6641 30.2347 14.6687H1.37146C0.618395 14.6687 0.00317759 15.2718 0.000217784 16.0133C-0.0111986 18.6299 0.42643 21.1587 1.26532 23.3256C2.26024 25.8956 3.74015 27.7874 5.66318 28.949C7.82003 30.2511 11.3316 30.998 15.2969 30.998C17.1523 30.998 19.0018 30.833 20.6449 30.5204C23.2343 30.0285 25.5852 29.187 27.6317 28.0204C29.4165 27.003 31.0194 25.7088 32.3962 24.175C34.6833 21.6251 36.0456 18.7771 37.0587 16.2567C37.1953 16.2621 37.3298 16.2646 37.4625 16.2646C39.9661 16.2646 41.5056 15.2785 42.3559 14.4507C43.2781 13.5529 43.6062 12.6581 43.6405 12.5589L43.8198 12.0416L43.3876 11.6998Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M4.04572 13.8376H7.91377C8.10024 13.8376 8.25203 13.6884 8.25203 13.5038V10.1073C8.25203 9.92265 8.10024 9.77344 7.91377 9.77344H4.04572C3.85883 9.77344 3.70703 9.92265 3.70703 10.1073V13.5038C3.70703 13.6884 3.85883 13.8376 4.04572 13.8376Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M9.37775 13.8376H13.2449C13.4323 13.8376 13.5836 13.6884 13.5836 13.5038V10.1073C13.5836 9.92265 13.4323 9.77344 13.2449 9.77344H9.37775C9.19044 9.77344 9.03906 9.92265 9.03906 10.1073V13.5038C9.03906 13.6884 9.19044 13.8376 9.37775 13.8376Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M14.7894 13.8376H18.6571C18.8439 13.8376 18.9957 13.6884 18.9957 13.5038V10.1073C18.9957 9.92265 18.8439 9.77344 18.6571 9.77344H14.7894C14.6025 9.77344 14.4512 9.92265 14.4512 10.1073V13.5038C14.4512 13.6884 14.6025 13.8376 14.7894 13.8376Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M20.1375 13.8376H24.0051C24.1925 13.8376 24.3438 13.6884 24.3438 13.5038V10.1073C24.3438 9.92265 24.1925 9.77344 24.0051 9.77344H20.1375C19.951 9.77344 19.7988 9.92265 19.7988 10.1073V13.5038C19.7988 13.6884 19.951 13.8376 20.1375 13.8376Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M9.37775 8.95092H13.2449C13.4323 8.95092 13.5836 8.8017 13.5836 8.61748V5.22057C13.5836 5.03635 13.4323 4.88672 13.2449 4.88672H9.37775C9.19044 4.88672 9.03906 5.03635 9.03906 5.22057V8.61748C9.03906 8.8017 9.19044 8.95092 9.37775 8.95092Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M14.7894 8.95092H18.6571C18.8439 8.95092 18.9957 8.8017 18.9957 8.61748V5.22057C18.9957 5.03635 18.8439 4.88672 18.6571 4.88672H14.7894C14.6025 4.88672 14.4512 5.03635 14.4512 5.22057V8.61748C14.4512 8.8017 14.6025 8.95092 14.7894 8.95092Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M20.1356 8.95092H24.0032C24.1905 8.95092 24.3419 8.8017 24.3419 8.61748V5.22057C24.3419 5.03635 24.1905 4.88672 24.0032 4.88672H20.1356C19.9491 4.88672 19.7969 5.03635 19.7969 5.22057V8.61748C19.7969 8.8017 19.9491 8.95092 20.1356 8.95092Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M20.1356 4.0642H24.0032C24.1905 4.0642 24.3419 3.91457 24.3419 3.73034V0.333855C24.3419 0.149214 24.1905 0 24.0032 0H20.1356C19.9491 0 19.7969 0.149214 19.7969 0.333855V3.73034C19.7969 3.91457 19.9491 4.0642 20.1356 4.0642Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M25.532 13.8376H29.3992C29.5866 13.8376 29.7379 13.6884 29.7379 13.5038V10.1073C29.7379 9.92265 29.5866 9.77344 29.3992 9.77344H25.532C25.3447 9.77344 25.1934 9.92265 25.1934 10.1073V13.5038C25.1934 13.6884 25.3447 13.8376 25.532 13.8376Z" />
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

19
metadata.json Normal file
View File

@ -0,0 +1,19 @@
{
"icon": "docker.svg",
"vm": {
"composefile": "docker-compose.yaml",
"exposes": {
"socket": "backend.sock"
}
},
"ui": {
"dashboard-tab": {
"title": "Postgressql",
"src": "index.html",
"root": "ui",
"backend": {
"socket": "backend.sock"
}
}
}
}

BIN
ui/.DS_Store vendored Normal file

Binary file not shown.

1
ui/.browserslistrc Normal file
View File

@ -0,0 +1 @@
Electron 17.1.1

1
ui/.env Normal file
View File

@ -0,0 +1 @@
BROWSER=none

12
ui/index.html Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="color-scheme" content="light dark" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

10519
ui/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

31
ui/package.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "ui",
"version": "0.1.0",
"private": true,
"type": "module",
"dependencies": {
"@docker/docker-mui-theme": "<0.1.0",
"@docker/extension-api-client": "0.3.3",
"@emotion/react": "11.10.4",
"@emotion/styled": "11.10.4",
"@mui/material": "5.10.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"test": "jest src"
},
"devDependencies": {
"@docker/extension-api-client-types": "0.3.3",
"@types/jest": "^29.1.2",
"@types/node": "^18.7.18",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^2.1.0",
"jest": "^29.1.2",
"typescript": "^4.8.3",
"vite": "^3.1.0"
}
}

53
ui/src/App.tsx Normal file
View File

@ -0,0 +1,53 @@
import React from 'react';
import Button from '@mui/material/Button';
import { createDockerDesktopClient } from '@docker/extension-api-client';
import { Stack, TextField, Typography } from '@mui/material';
// Note: This line relies on Docker Desktop's presence as a host application.
// If you're running this React app in a browser, it won't work properly.
const client = createDockerDesktopClient();
function useDockerDesktopClient() {
return client;
}
export function App() {
const [response, setResponse] = React.useState<string>();
const ddClient = useDockerDesktopClient();
const fetchAndDisplayResponse = async () => {
const result = await ddClient.extension.vm?.service?.get('/hello');
setResponse(JSON.stringify(result));
};
return (
<>
<Typography variant="h3">Docker extension demo</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mt: 2 }}>
This is a basic page rendered with MUI, using Docker's theme. Read the
MUI documentation to learn more. Using MUI in a conventional way and
avoiding custom styling will help make sure your extension continues to
look great as Docker's theme evolves.
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mt: 2 }}>
Pressing the below button will trigger a request to the backend. Its
response will appear in the textarea.
</Typography>
<Stack direction="row" alignItems="start" spacing={2} sx={{ mt: 4 }}>
<Button variant="contained" onClick={fetchAndDisplayResponse}>
Call backend
</Button>
<TextField
label="Backend response"
sx={{ width: 480 }}
disabled
multiline
variant="outlined"
minRows={5}
value={response ?? ''}
/>
</Stack>
</>
);
}

20
ui/src/main.tsx Normal file
View File

@ -0,0 +1,20 @@
import React from "react";
import ReactDOM from "react-dom/client";
import CssBaseline from "@mui/material/CssBaseline";
import { DockerMuiThemeProvider } from "@docker/docker-mui-theme";
import { App } from './App';
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
{/*
If you eject from MUI (which we don't recommend!), you should add
the `dockerDesktopTheme` class to your root <html> element to get
some minimal Docker theming.
*/}
<DockerMuiThemeProvider>
<CssBaseline />
<App />
</DockerMuiThemeProvider>
</React.StrictMode>
);

1
ui/src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

21
ui/tsconfig.json Normal file
View File

@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

9
ui/tsconfig.node.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

15
ui/vite.config.ts Normal file
View File

@ -0,0 +1,15 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
base: "./",
build: {
outDir: "build",
},
server: {
port: 3000,
strictPort: true,
}
});