Skip to content

Commit 501698d

Browse files
committed
Bundle database init scripts in postgres image
1 parent 690cdfa commit 501698d

7 files changed

Lines changed: 60 additions & 13 deletions

File tree

.env.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ BASIC_AUTH_PASSWORD=change-this-password
1010

1111
# TeslaMate collector stack. Generate strong values before production use:
1212
# openssl rand -base64 48
13-
POSTGRES_TAG=18-trixie
1413
MOSQUITTO_TAG=2
1514
TESLAMATE_TAG=latest
1615
TM_ENCRYPTION_KEY=replace-with-a-long-random-encryption-key

.github/workflows/publish.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@ jobs:
2121
include:
2222
- image: tesla-dashboard-api
2323
context: ./backend
24+
file: ./backend/Dockerfile
2425
- image: tesla-dashboard-web
2526
context: ./frontend
27+
file: ./frontend/Dockerfile
28+
- image: tesla-dashboard-postgres
29+
context: ./deploy
30+
file: ./deploy/Dockerfile.postgres
2631

2732
steps:
2833
- name: Checkout
@@ -60,6 +65,7 @@ jobs:
6065
uses: docker/build-push-action@v6
6166
with:
6267
context: ${{ matrix.context }}
68+
file: ${{ matrix.file }}
6369
push: true
6470
platforms: linux/amd64
6571
tags: ${{ steps.tags.outputs.tags }}

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Nginx / Frontend -- 内网 HTTP --> FastAPI Backend -- Docker 内网 --> Pos
1616
TeslaMate Collector -- 内网 --> PostgreSQL + MQTT
1717
```
1818

19-
默认生产部署只发布 `web``WEB_PORT``api` 只在 Docker 内网暴露 `8000`,TeslaMate 只在 Docker 内网暴露 `4000`,PostgreSQL 和 MQTT 也都只在内网可见。`db-init` 服务会自动创建只读数据库账号,不需要手工执行 SQL。
19+
默认生产部署只发布 `web``WEB_PORT``api` 只在 Docker 内网暴露 `8000`,TeslaMate 只在 Docker 内网暴露 `4000`,PostgreSQL 和 MQTT 也都只在内网可见。`database` 镜像内置首次启动恢复备份脚本,`db-init` 服务会自动创建只读数据库账号,不需要手工执行 SQL,也不需要在部署目录额外复制脚本文件
2020

2121
## 功能
2222

@@ -92,7 +92,6 @@ WEB_PORT=8080
9292
BASIC_AUTH_USER=admin
9393
BASIC_AUTH_PASSWORD=change-this-password
9494
95-
POSTGRES_TAG=18-trixie
9695
MOSQUITTO_TAG=2
9796
TESLAMATE_TAG=latest
9897
TM_ENCRYPTION_KEY=replace-with-a-long-random-encryption-key
@@ -115,6 +114,14 @@ openssl rand -base64 48
115114

116115
大陆机器部署前,先在 GitHub Actions 手工运行一次 `Build and Push Images`,把本项目镜像和运行依赖镜像都推送到阿里云镜像仓库。生产 `compose.yaml` 默认会从 `${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}` 拉取所有镜像,不再直接依赖 Docker Hub。
117116

117+
生产部署目录最少只需要这些文件:
118+
119+
- `compose.yaml`
120+
- `.env`
121+
- 可选的 TeslaMate 数据库备份文件,例如 `teslamate.bck`
122+
123+
恢复备份和创建只读账号的脚本已经打进 `tesla-dashboard-postgres` 镜像,不需要额外复制 `deploy/` 目录。
124+
118125
### 2. 启动
119126

120127
先确认部署机有 Docker Compose v2:
@@ -159,6 +166,18 @@ http://部署机IP:8080
159166

160167
如果备份里包含旧的 TeslaMate token,并且 `TM_ENCRYPTION_KEY` 也保持一致,那么恢复后通常可以直接继续使用,不需要重新额外配置授权 token。
161168

169+
完整重建并重新导入备份:
170+
171+
```bash
172+
sudo docker compose down -v --remove-orphans
173+
sudo docker compose pull
174+
sudo docker compose up -d database
175+
sudo docker compose logs -f database
176+
sudo docker compose up -d
177+
```
178+
179+
`down -v` 会删除 PostgreSQL 持久化 volume。只有在确认同级目录里的备份文件可用时才执行这条命令。
180+
162181
## GitHub Actions 推送到阿里云镜像仓库
163182

164183
工作流在 [.github/workflows/publish.yml](.github/workflows/publish.yml)。在 GitHub 仓库的 `Settings -> Secrets and variables -> Actions` 添加:
@@ -175,6 +194,7 @@ http://部署机IP:8080
175194
```text
176195
registry.cn-shenzhen.aliyuncs.com/your-namespace/tesla-dashboard-api:<image_tag>
177196
registry.cn-shenzhen.aliyuncs.com/your-namespace/tesla-dashboard-web:<image_tag>
197+
registry.cn-shenzhen.aliyuncs.com/your-namespace/tesla-dashboard-postgres:<image_tag>
178198
registry.cn-shenzhen.aliyuncs.com/your-namespace/postgres:18-trixie
179199
registry.cn-shenzhen.aliyuncs.com/your-namespace/eclipse-mosquitto:2
180200
registry.cn-shenzhen.aliyuncs.com/your-namespace/teslamate:latest

compose.yaml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ name: tesla-dashboard
22

33
services:
44
database:
5-
image: ${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/postgres:${POSTGRES_TAG:-18-trixie}
5+
image: ${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/tesla-dashboard-postgres:${IMAGE_TAG:-latest}
66
restart: unless-stopped
77
environment:
88
POSTGRES_USER: ${TM_DB_USER:-teslamate}
99
POSTGRES_PASSWORD: ${TM_DB_PASS}
1010
POSTGRES_DB: ${TM_DB_NAME:-teslamate}
1111
volumes:
1212
- teslamate-db:/var/lib/postgresql
13-
- ./deploy/restore-backup-if-present.sh:/docker-entrypoint-initdb.d/20-restore-backup-if-present.sh:ro
1413
- ./:/backup-source:ro
1514
networks:
1615
- data
@@ -62,7 +61,7 @@ services:
6261
- all
6362

6463
db-init:
65-
image: ${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/postgres:${POSTGRES_TAG:-18-trixie}
64+
image: ${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/tesla-dashboard-postgres:${IMAGE_TAG:-latest}
6665
restart: "no"
6766
depends_on:
6867
database:
@@ -74,9 +73,7 @@ services:
7473
POSTGRES_DB: ${TM_DB_NAME:-teslamate}
7574
DASHBOARD_DB_USER: ${DASHBOARD_DB_USER:-dashboard_readonly}
7675
DASHBOARD_DB_PASSWORD: ${DASHBOARD_DB_PASSWORD}
77-
volumes:
78-
- ./deploy/create-dashboard-role.sh:/scripts/create-dashboard-role.sh:ro
79-
command: ["sh", "/scripts/create-dashboard-role.sh"]
76+
command: ["sh", "/usr/local/share/tesla-dashboard/create-dashboard-role.sh"]
8077
networks:
8178
- data
8279
security_opt:

deploy/Dockerfile.postgres

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
ARG POSTGRES_IMAGE=postgres:18-trixie
2+
FROM ${POSTGRES_IMAGE}
3+
4+
COPY restore-backup-if-present.sh /docker-entrypoint-initdb.d/20-restore-backup-if-present.sh
5+
COPY create-dashboard-role.sh /usr/local/share/tesla-dashboard/create-dashboard-role.sh
6+
7+
RUN chmod 0755 /docker-entrypoint-initdb.d/20-restore-backup-if-present.sh \
8+
/usr/local/share/tesla-dashboard/create-dashboard-role.sh

deploy/create-dashboard-role.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ set -eu
1010

1111
export PGPASSWORD="$POSTGRES_PASSWORD"
1212

13+
echo "Waiting for PostgreSQL at $POSTGRES_HOST..."
1314
until pg_isready -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; do
1415
sleep 1
1516
done
1617

18+
echo "Creating or updating read-only dashboard role: $DASHBOARD_DB_USER"
1719
psql \
1820
-h "$POSTGRES_HOST" \
1921
-U "$POSTGRES_USER" \
@@ -52,3 +54,5 @@ begin
5254
end
5355
$$;
5456
SQL
57+
58+
echo "Read-only dashboard role is ready: $DASHBOARD_DB_USER"

deploy/restore-backup-if-present.sh

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,33 @@ fi
4646

4747
echo "Restoring TeslaMate database backup: $backup_file"
4848

49+
restore_dump_or_sql() {
50+
candidate="$1"
51+
52+
if pg_restore --list "$candidate" >/dev/null 2>&1; then
53+
pg_restore --verbose --no-owner --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" "$candidate"
54+
else
55+
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < "$candidate"
56+
fi
57+
}
58+
4959
case "$backup_file" in
5060
*.sql|*.bck)
51-
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < "$backup_file"
61+
restore_dump_or_sql "$backup_file"
5262
;;
5363
*.sql.gz|*.bck.gz)
54-
gzip -dc "$backup_file" | psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB"
64+
tmp_file="/tmp/teslamate-restore"
65+
gzip -dc "$backup_file" > "$tmp_file"
66+
restore_dump_or_sql "$tmp_file"
67+
rm -f "$tmp_file"
5568
;;
5669
*.dump|*.backup)
57-
pg_restore --verbose --no-owner --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" "$backup_file"
70+
restore_dump_or_sql "$backup_file"
5871
;;
5972
*.dump.gz|*.backup.gz)
6073
tmp_file="/tmp/teslamate-restore.dump"
6174
gzip -dc "$backup_file" > "$tmp_file"
62-
pg_restore --verbose --no-owner --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" "$tmp_file"
75+
restore_dump_or_sql "$tmp_file"
6376
rm -f "$tmp_file"
6477
;;
6578
*)

0 commit comments

Comments
 (0)