diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fced889
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+default: help
+help:  ## Display this help
+	@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n  make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf "  \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
+.PHONY: help
+
+run-api7:
+	@docker login hkccr.ccs.tencentyun.com -u 100033089146 -p "{e>rw2[#EDAD" ## read only account
+	@docker compose -f ./e2e/api7/docker-compose.yaml up -d
+	@./e2e/api7/init.sh
+.PHONY: run-api7
diff --git a/e2e/api7/dashboard.yaml b/e2e/api7/dashboard.yaml
new file mode 100644
index 0000000..f6bb256
--- /dev/null
+++ b/e2e/api7/dashboard.yaml
@@ -0,0 +1,10 @@
+server:
+  listen:
+    host: "0.0.0.0"
+    port: 7080
+
+database:
+  dsn: "postgres://api7ee:changeme@postgresql:5432/api7ee"
+
+prometheus:
+  addr: "http://prometheus:9090"
diff --git a/e2e/api7/docker-compose.yaml b/e2e/api7/docker-compose.yaml
new file mode 100644
index 0000000..33b13ba
--- /dev/null
+++ b/e2e/api7/docker-compose.yaml
@@ -0,0 +1,74 @@
+version: "3.6"
+
+services:
+  prometheus:
+    image: bitnami/prometheus:2.44.0-debian-11-r7
+    hostname: prometheus
+    command:
+      - --config.file=/opt/bitnami/prometheus/conf/prometheus.yml
+      - --web.enable-remote-write-receiver
+    healthcheck:
+      test: ["CMD", "/opt/bitnami/prometheus/bin/promtool", "check", "healthy"]
+      interval: 10s
+      timeout: 10s
+      retries: 3
+      start_period: 10s
+    networks:
+      - api7
+
+  postgresql:
+    image: bitnami/postgresql:15.3.0-debian-11-r0
+    hostname: postgresql
+    user: root
+    ports:
+      - "5432:5432"
+    healthcheck:
+      test: ["CMD", "pg_isready", "-U", "api7ee"]
+      interval: 10s
+      timeout: 10s
+      retries: 3
+      start_period: 10s
+    environment:
+      POSTGRES_USER: api7ee
+      POSTGRES_PASSWORD: changeme
+    networks:
+      - api7
+
+  api7-ee-dashboard:
+    image: hkccr.ccs.tencentyun.com/api7-dev/api7-ee-3:dev
+    hostname: dashboard
+    restart: always
+    volumes:
+      - ./dashboard.yaml:/usr/local/api7/conf/conf.yaml:ro
+    entrypoint:
+      - /usr/local/api7/api7-ee-dashboard
+      - -c
+      - /usr/local/api7/conf/conf.yaml
+    ports:
+      - "7080:7080"
+    depends_on:
+      prometheus:
+        condition: service_healthy
+    networks:
+      - api7
+
+  api7-ee-dp-manager:
+    image: hkccr.ccs.tencentyun.com/api7-dev/api7-ee-dp-manager:dev
+    hostname: dp-manager
+    restart: always
+    volumes:
+      - ./dp-manager.yaml:/usr/local/api7/conf/conf.yaml:ro
+    command:
+      - /usr/local/api7/api7-ee-dp-manager
+      - -c
+      - /usr/local/api7/conf/conf.yaml
+    ports:
+      - "7900:7900"
+    networks:
+      - api7
+
+networks:
+  api7:
+    driver: bridge
+    ipam:
+      driver: default
diff --git a/e2e/api7/dp-manager.yaml b/e2e/api7/dp-manager.yaml
new file mode 100644
index 0000000..58c665f
--- /dev/null
+++ b/e2e/api7/dp-manager.yaml
@@ -0,0 +1,10 @@
+server:
+  listen:
+    host: "0.0.0.0"
+    port: 7900
+
+database:
+  dsn: "postgres://api7ee:changeme@postgresql:5432/api7ee"
+
+prometheus:
+  addr: "http://prometheus:9090"
diff --git a/e2e/api7/init.sh b/e2e/api7/init.sh
new file mode 100755
index 0000000..72267c4
--- /dev/null
+++ b/e2e/api7/init.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+set -o errexit
+set -o nounset
+set -o pipefail
+
+while ! curl -m 1 --output /dev/null --silent --fail http://localhost:7080/healthz;
+do
+    echo "Waiting dashboard ready..." && sleep 1;
+done
+
+curl --user admin:admin 'http://localhost:7080/api/license' \
+  -X 'PUT' \
+  -H 'Content-Type: application/json' \
+  --data-raw '{"data":"jEDPm798nC4jnemMZ_6gdxRn0dgxecVY-cRHD6Smuz0Hp_mtrsKJCO_xsLws-zcL_ON0LJFXmLfLAON84NjfhmuayyZ9-GdWSan2COqw0X1cdWDOfDxeJ55jmo5SlVmNufIxFv275pQGNLt7gwhRt6KEpDZLRaJRJx51IcXgCvYI46xoqJYm-CE2tk69HbnTUXM25pzVTaon7UKEmy4SWsXjN6X4dw6H39j_fHCtdBfDXrX9ppYORL1LvTf4jIe6BP9vubLutYTM7R3bk523-EbDuUAMVLzOjngKp3oGJ6IHS52Hue4a2POMiIn4JPHNussR-_VRSFK5Eomfs_MRlw\n"}' -s --output /dev/null
+
+access_token=$(curl --user admin:admin 'http://localhost:7080/api/settings/tokens' \
+  -H 'Content-Type: application/json' \
+  --data-raw '{"expires_at":0,"name":"'$(uuidgen)'"}' -s | jq -r .value.token)
+
+echo "access token: " $access_token