# Compose 访问计数器

配套教学页：`../project-deploy.html`。建议在上一页准备的 Ubuntu 26.04 LTS
云服务器或练习虚拟机上运行。需要 Git、Docker Engine 与 Compose 插件，当前账号
应已能使用 Docker；安装方法见 Docker 官方 Ubuntu 安装文档：
https://docs.docker.com/engine/install/ubuntu/

## 从 clone 到本机验证

```sh
git clone https://forgejo.farstarhq.com/learning/linux-start.git
cd linux-start/pages/linux-project/project-deploy
cp .env.example .env
chmod 600 .env
# 用编辑器修改 .env 中的 APP_MESSAGE，保留单引号。
docker compose config --quiet
docker compose up -d --build --wait
curl --fail-with-body http://127.0.0.1:8080/healthz
curl --fail-with-body http://127.0.0.1:8080/
docker compose ps
docker compose logs --tail=50 app
```

`/` 返回 JSON（带有 message 与 visits），每次访问加一；`/healthz` 验证数据库可读，
不会增加计数。数据库是嵌入应用进程的 SQLite，文件位于 `/data/visits.sqlite3`，
由命名卷 `app_data` 保存，没有单独的数据库服务和数据库密码。

此 PR 合并前，main 中可能还没有示例；审阅时可 clone 后执行
`git switch --track origin/case/issue-63` 再进入示例目录。

## 接入公网 HTTPS

1. 将你拥有的域名 A 记录指向服务器公网 IPv4；如存在 AAAA，必须同样指向可用的
   IPv6。等待 DNS 生效。`.env` 中把 `DOMAIN` 改成这个主机名，不能带协议或路径。
2. 在云安全组与主机防火墙允许入站 TCP 80、443，保留上一页的 SSH 入口。
   确保没有其他服务占用 80/443，且服务器能出站访问 DNS、镜像仓库和证书机构。
3. 在同一个项目目录执行：

```sh
docker compose --profile https config --quiet
docker compose --profile https up -d --build --wait
docker compose logs --tail=80 caddy
```

在自己的电脑浏览器访问 `https://你的域名/`，或用 curl 访问它；不使用 `-k`。
Caddy 自动申请、续期证书并把 HTTP 重定向到 HTTPS。没有域名时先完成本机验证，
不要把 `localhost` 当成公网证书测试。公网签发依赖真实 DNS 和网络条件。

如需浏览器验证本机入口，在自己的电脑建立 SSH 转发（替换账号和服务器地址）：

```sh
ssh -N -L 18080:127.0.0.1:8080 ubuntu@你的服务器公网IP
```

然后在自己电脑打开 `http://127.0.0.1:18080/`；用完 Ctrl+C 结束转发。

## 更新、停止与排障

- 修改 `.env` 后重新执行 `up -d --build --wait`；仅 `restart` 不会注入新配置。
- 拉取源码更新：`git pull --ff-only`，再执行对应 profile 的 `up -d --build --wait`。
- 试验持久化：访问 `/`，执行 `docker compose up -d --force-recreate --wait app`，
  再访问 `/`，计数应接着增加。
- 停止本机示例：`docker compose down`。启用过 HTTPS 则用
  `docker compose --profile https down`。这会保留命名卷。
- **不要给日常停止命令加 `-v`**：它会删除声明的命名卷，包括计数与证书存储。
  保持同一项目名 `linux-counter` 才能重新挂回原卷；另一份并行练习应修改项目名和宿主机端口。
- 配置报错先看工作目录、`.env` 和 shell 中的同名变量；连接失败先看 `ps`、app 日志；
  502 看 Caddy 能否访问 `app:8000`；证书失败看 DNS、80/443 和 Caddy 日志。

这是无登录功能的教学计数器，不保存敏感信息。Python 标准库 `http.server` 用来让
示例零第三方依赖；正式业务应换用合适的应用服务器，补齐认证、限流、备份和监控。
`.env` 不会自动进容器，本例只显式传入 APP_MESSAGE / DOMAIN；真实凭据不要提交 Git，
也不要粘贴完整 `docker compose config` 输出。示例的两个镜像标签会随上游更新；
需精确复现时记录镜像 digest 与 Git 提交。

## 无 Docker 的代码验证

可在临时目录设置 `DATABASE_PATH` 指向测试文件、`PORT` 指向空闲端口，
运行 `python3 app.py`，用 curl 验证端点与进程重启后的持久化。这只能验证应用代码，
不能代替容器构建、卷权限、Compose 网络和公网证书签发测试。
