Skip to content

Commit

Permalink
Add docker compose support (#217)
Browse files Browse the repository at this point in the history
* Add new platform type for docker-compose

Signed-off-by: Tim Callaghan <[email protected]>

* Update readme to include setup process for docker compose
Update dev docs with information on defining a new platform

Signed-off-by: Tim Callaghan <[email protected]>

* Typo

Signed-off-by: Tim Callaghan <[email protected]>

* Update platform.md

Signed-off-by: Artur Souza <[email protected]>

* Fix conflict resolution in instances.go

Signed-off-by: Artur Souza <[email protected]>

* Fix compilation after merge conflicts.

Signed-off-by: Artur Souza <[email protected]>

* Fixing lint errors.

Signed-off-by: Artur Souza <[email protected]>

---------

Signed-off-by: Tim Callaghan <[email protected]>
Signed-off-by: Artur Souza <[email protected]>
Co-authored-by: Artur Souza <[email protected]>
  • Loading branch information
timcallaghan and artursouza authored Apr 19, 2023
1 parent bd475ec commit 943b638
Show file tree
Hide file tree
Showing 12 changed files with 517 additions and 54 deletions.
105 changes: 100 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,35 @@
[![codecov](https://codecov.io/gh/dapr/dashboard/branch/master/graph/badge.svg)](https://codecov.io/gh/dapr/dashboard)
[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fdapr%2Fdashboard.svg?type=shield)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fdapr%2Fdashboard?ref=badge_shield)

Dapr Dashboard is a web-based UI for Dapr, allowing users to see information, view logs and more for the Dapr applications, components, and configurations running either locally or in a Kubernetes cluster.
Dapr Dashboard is a web-based UI for Dapr, allowing users to see information, view logs and more for the Dapr applications, components, and configurations running on a supported Dapr Dashboard platform.

Supported Dapr Dashboard plaforms are:
- Standalone - running locally via Dapr CLI
- Kubernetes - running inside a Kubernetes cluster
- Docker Compose - running inside a docker compose network

<p style="text-align:center">
<img src="img/img.PNG">
</p>

## Features

Dapr Dashboard provides information about Dapr applications, components, configurations, and control plane services. Users can view metadata, manifests and deployment files, actors, logs, and more on both Kubernetes and self-hosted platforms. For more information, check out the [changelog](docs/development/changelog.md).
Dapr Dashboard provides information about Dapr applications, components, configurations, and control plane services (Kubernetes only). Users can view metadata, manifests and deployment files, actors, logs, and more. For more information, check out the [changelog](docs/development/changelog.md).

## Getting started

### Prerequisites
[Dapr Runtime](https://github.com/dapr/dapr)

[Dapr CLI](https://github.com/dapr/cli)
If you intend to run in the Standalone or Kubernetes platform mode you will need to have the following:

### Installation
- [Dapr Runtime](https://github.com/dapr/dapr)
- [Dapr CLI](https://github.com/dapr/cli)

Dapr Dashboard comes pre-packaged with the Dapr CLI. To learn more about the dashboard command, use the CLI command `dapr dashboard -h`.

If you intend to run in the Docker Compose platform mode, you don't need to install anything. Instead you specify Dapr docker images to use.

### Installation
If you want to install via Helm, run:
```sh
helm repo add dapr https://dapr.github.io/helm-charts/
Expand All @@ -37,6 +45,93 @@ Run `dapr dashboard -k`, or if you installed Dapr in a non-default namespace, `d
#### Standalone
Run `dapr dashboard`, and navigate to http://localhost:8080.

#### Docker Compose
Construct a docker compose file that references the specific Dapr pieces that you want to use. The following example defines an application and its corresponding daprd sidecar, the Dapr Placement service, and the Dapr Dashboard.

When running inside docker compose, the dashboard needs access to the component and configuration files that are passed to the daprd services. It also needs to know about all daprd services running inside the docker compose network - it retrieves this by parsing the docker-compose.yml file. To achieve this, you define docker bind mounts to these files/directories and pass them as command args to the dashboard process. In addition, you must specify the command arg `--docker-compose=true` to tell the dashboard to use the docker compose platform type.

```yml
version: '3.8'
services:

my-application-webhost:
build:
context: .
dockerfile: src/My.Application.WebHost/Dockerfile
ports:
- "5002:80"
networks:
- my-network

my-application-webhost-dapr:
image: "daprio/daprd:1.8.0"
command: [ "./daprd",
"-app-id", "MyApplication.DaprSidecar",
"-app-port", "80",
"-placement-host-address", "dapr-placement:50000",
"-components-path", "/components",
"-config", "/configuration/config.yaml" ]
volumes:
- "./dockercompose/dapr/components/:/components"
- "./dockercompose/dapr/config/:/configuration"
depends_on:
- my-application-webhost
- dapr-placement
network_mode: "service:my-application-webhost"

dapr-placement:
image: "daprio/dapr:1.8.0"
command: [ "./placement", "-port", "50000" ]
ports:
- "50000:50000"
networks:
- my-network

dapr-dashboard:
image: "daprio/dashboard:latest"
command: [ "--docker-compose=true",
"--components-path=/home/nonroot/components",
"--config-path=/home/nonroot/configuration",
"--docker-compose-path=/home/nonroot/docker-compose.yml" ]
ports:
- "8080:8080"
volumes:
- "./dockercompose/dapr/components/:/home/nonroot/components"
- "./dockercompose/dapr/config/:/home/nonroot/configuration"
- ./docker-compose.yml:/home/nonroot/docker-compose.yml
networks:
- my-network

networks:
my-network:
```
The above example assumes the following file system layout
```
dockercompose
dapr
components
(component yaml files e.g. pubsub.yaml, statestore.yaml etc.)
config
config.yaml
src
My.Application.WebHost
Dockerfile
docker-compose.yml
```

If you have configured your Dapr sidecars to require [API token authentication](https://docs.dapr.io/operations/security/api-token/), you can set the environment variable `DAPR_API_TOKEN: {your token}` on the Dapr Dashboard service declaration as follows
```yml
dapr-dashboard:
image: "daprio/dashboard:latest"
environment:
DAPR_API_TOKEN: {your token}
...
```

For more information about running Dapr with docker compose see [Run using Docker-Compose](https://docs.dapr.io/operations/hosting/self-hosted/self-hosted-with-docker/#run-using-docker-compose)

### Contributing
Anyone is free to open an issue, a feature request, or a pull request.

Expand Down
28 changes: 27 additions & 1 deletion cmd/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,39 @@ import (
func RunDashboard() {
dashboardVersion := flag.Bool("version", false, "Prints the dashboard version")
port := flag.Int("port", 8080, "Port to listen to")
dockerCompose := flag.Bool("docker-compose", false, "Is running inside docker compose")
componentsPath := flag.String("components-path", "", "Path to volume mounted dapr components (docker-compose only)")
configPath := flag.String("config-path", "", "Path to volume mounted dapr configuration (docker-compose only)")
dockerComposePath := flag.String("docker-compose-path", "", "Path to volume mounted docker compose file (docker-compose only)")

flag.Parse()

fmt.Println(*dockerCompose)
fmt.Println(*componentsPath)
fmt.Println(*configPath)
fmt.Println(*dockerComposePath)

if *dockerCompose {
if len(*componentsPath) == 0 {
fmt.Println("--components-path required when --docker-compose=true")
os.Exit(1)
}

if len(*configPath) == 0 {
fmt.Println("--config-path required when --docker-compose=true")
os.Exit(1)
}

if len(*dockerComposePath) == 0 {
fmt.Println("--docker-compose-path required when --docker-compose=true")
os.Exit(1)
}
}

if *dashboardVersion {
fmt.Println(version.GetVersion())
os.Exit(0)
} else {
RunWebServer(*port)
RunWebServer(*port, *dockerCompose, *componentsPath, *configPath, *dockerComposePath)
}
}
21 changes: 11 additions & 10 deletions cmd/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
instances "github.com/dapr/dashboard/pkg/instances"
kube "github.com/dapr/dashboard/pkg/kube"
dashboard_log "github.com/dapr/dashboard/pkg/log"
"github.com/dapr/dashboard/pkg/platforms"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
)
Expand Down Expand Up @@ -77,18 +78,18 @@ var (
)

// RunWebServer starts the web server that serves the Dapr UI dashboard and the API
func RunWebServer(port int) {
platform := ""
func RunWebServer(port int, isDockerCompose bool, componentsPath string, configPath string, dockerComposePath string) {
platform := platforms.Standalone
kubeClient, daprClient, _ := kube.Clients()
if kubeClient != nil {
platform = "kubernetes"
} else {
platform = "standalone"
platform = platforms.Kubernetes
} else if isDockerCompose {
platform = platforms.DockerCompose
}

inst = instances.NewInstances(platform, kubeClient)
comps = components.NewComponents(platform, daprClient)
configs = configurations.NewConfigurations(platform, daprClient)
inst = instances.NewInstances(platform, kubeClient, dockerComposePath)
comps = components.NewComponents(platform, daprClient, componentsPath)
configs = configurations.NewConfigurations(platform, daprClient, configPath)

r := mux.NewRouter()
api := r.PathPrefix("/api/").Subrouter()
Expand Down Expand Up @@ -213,15 +214,15 @@ func getFeaturesHandler(w http.ResponseWriter, r *http.Request) {
if configs.Supported() {
features = append(features, "configurations")
}
if inst.CheckPlatform() == "kubernetes" {
if inst.CheckPlatform() == platforms.Kubernetes {
features = append(features, "status")
}
respondWithJSON(w, 200, features)
}

func getPlatformHandler(w http.ResponseWriter, r *http.Request) {
resp := inst.CheckPlatform()
respondWithPlainString(w, 200, resp)
respondWithPlainString(w, 200, string(resp))
}

func getContainersHandler(w http.ResponseWriter, r *http.Request) {
Expand Down
17 changes: 15 additions & 2 deletions docs/development/platform.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# Adding a new platform

Dashboard currently supports 2 platforms: Kubernetes and self-hosted (August 2020).
Dashboard currently supports 3 platforms: Kubernetes, self-hosted and docker-compose (April 2023).


## Backend

The application platform is defined in `cmd/webserver.go:RunWebServer()`. To add a new platform, logic needs to be defined here to determine how Dashboard will recognize it. Any API clients or other necessary structures should be passed as arguments to the constructor of `instances.NewInstances(...)` and the other backend struct constructors along with the platform.
Platform definitions are contained in [platforms.go](../../pkg/platforms/platforms.go). When adding a new platform, define a new constant for the platform in `platforms.go`.

If the new platform requires configuration arguments you can define optional go flags in [dashboard.go](../../cmd/dashboard.go) and pass them to `RunWebServer(...)` in [webserver.go](../../cmd/webserver.go).

The runtime application platform is defined in `cmd/webserver.go:RunWebServer()`. To add a new platform, logic needs to be defined here to determine how Dashboard will recognize it. Any API clients or other necessary structures should be passed as arguments to the constructor of `instances.NewInstances(...)` and the other backend struct constructors along with the platform.

In `pkg/instances.go`, `pkg/components.go`, and `pkg/configurations.go`, new methods should be defined for each new platform, following the current pattern. In these files, functions such as `GetInstance(scope string, id string)` and `GetScopes()` are defined. These abstracted functions will call the correct platform-specific function:

Expand All @@ -18,6 +22,15 @@ func (i *instances) GetInstances(scope string) []Instance {

Where `i.getInstanceFn` is defined in the constructor as `getPlatformInstances`, e.g. `getKubernetesInstances` or `getStandaloneInstances` according to the platform supplied.

If the new platform supports a feature (e.g. components) make sure you update the `func (c *type) Supported() bool` method in the corresponding package to include the platform definition. For example, in [components.go](../../pkg/components/components.go)

```go
// Supported checks whether or not the supplied platform is able to access Dapr components
func (c *components) Supported() bool {
return c.platform == platforms.Kubernetes || c.platform == platforms.Standalone || c.platform == platforms.DockerCompose
}
```

## Frontend

For platform-specific features of Dashboard, there is a service defined in `web/src/app/globals/globals.service.ts` that retrieves platform information from the backend. Any component that needs to know the current platform can make a call to this service and handle the returned data appropriately:
Expand Down
19 changes: 14 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ module github.com/dapr/dashboard
go 1.19

require (
github.com/compose-spec/compose-go v1.13.3
github.com/dapr/cli v1.10.0-rc.3
github.com/dapr/components-contrib v1.10.0-rc.4
github.com/dapr/dapr v1.10.0-rc.5
github.com/dapr/kit v0.0.4
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/stretchr/testify v1.8.1
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/stretchr/testify v1.8.2
k8s.io/api v0.26.1
k8s.io/apimachinery v0.26.1
k8s.io/client-go v1.5.2
Expand All @@ -26,12 +30,12 @@ require (
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/briandowns/spinner v1.21.0 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/containerd v1.6.16 // indirect
github.com/dapr/components-contrib v1.10.0-rc.4 // indirect
github.com/dapr/kit v0.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v23.0.0+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
Expand Down Expand Up @@ -61,6 +65,7 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/grandcat/zeroconf v1.0.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
Expand All @@ -69,7 +74,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.1 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/jhump/protoreflect v1.14.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
Expand All @@ -80,8 +85,10 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/microsoft/durabletask-go v0.1.3 // indirect
github.com/miekg/dns v1.1.43 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
Expand All @@ -102,7 +109,6 @@ require (
github.com/prometheus/statsd_exporter v0.23.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/spf13/cast v1.5.0 // indirect
Expand All @@ -114,6 +120,9 @@ require (
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.44.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.13.0 // indirect
Expand Down
Loading

0 comments on commit 943b638

Please sign in to comment.