docker配置
This commit is contained in:
12
.dockerignore
Normal file
12
.dockerignore
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.git
|
||||||
|
__pycache__/
|
||||||
|
venv/
|
||||||
|
*.pyc
|
||||||
|
*.log
|
||||||
|
*.backup
|
||||||
|
*_old.*
|
||||||
|
.last_*
|
||||||
|
debug_page.html
|
||||||
|
monitor.log
|
||||||
|
config.ini
|
||||||
|
data/
|
||||||
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PYTHONUNBUFFERED=1 \
|
||||||
|
GPA_DATA_DIR=/data
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& useradd --create-home --shell /usr/sbin/nologin appuser \
|
||||||
|
&& mkdir -p /data \
|
||||||
|
&& chown -R appuser:appuser /app /data
|
||||||
|
|
||||||
|
COPY requirements.txt /app/
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY monitor.py /app/
|
||||||
|
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
CMD ["python", "/app/monitor.py", "--config", "/data/config.ini"]
|
||||||
10
docker-compose.yml
Normal file
10
docker-compose.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
services:
|
||||||
|
gpa-monitor:
|
||||||
|
build: .
|
||||||
|
container_name: gpa-monitor
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
GPA_DATA_DIR: /data
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
- ./config.ini:/data/config.ini:ro
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
- Python 3.7+
|
- Python 3.7+
|
||||||
- 服务器能访问外网
|
- 服务器能访问外网
|
||||||
- SSH访问权限
|
- SSH访问权限
|
||||||
|
- (可选)Docker 20+ / Docker Compose v2
|
||||||
|
|
||||||
## 📦 项目文件说明
|
## 📦 项目文件说明
|
||||||
|
|
||||||
@@ -127,6 +128,45 @@ python3 monitor.py --test
|
|||||||
cat .last_grade_content.txt
|
cat .last_grade_content.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐳 Docker 部署(推荐)
|
||||||
|
|
||||||
|
> 适合已有 Docker 环境的服务器(例如 docker.aizhangz.top)。
|
||||||
|
|
||||||
|
### 1) 准备文件(本地或服务器)
|
||||||
|
|
||||||
|
必需文件:
|
||||||
|
- `monitor.py`
|
||||||
|
- `requirements.txt`
|
||||||
|
- `Dockerfile`
|
||||||
|
- `docker-compose.yml`
|
||||||
|
- `config.ini`(⚠️ 敏感文件)
|
||||||
|
|
||||||
|
### 2) 在服务器上运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入项目目录
|
||||||
|
cd ~/grade_monitor
|
||||||
|
|
||||||
|
# 首次构建并启动
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
docker logs -f gpa-monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) 测试模式(可选)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose run --rm gpa-monitor python /app/monitor.py --config /data/config.ini --test
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4) 说明
|
||||||
|
|
||||||
|
- 运行日志和缓存文件会写入 `./data/`
|
||||||
|
- 配置文件通过 `./config.ini:/data/config.ini:ro` 挂载
|
||||||
|
|
||||||
## 🔧 设置后台运行
|
## 🔧 设置后台运行
|
||||||
|
|
||||||
### 使用 systemd(推荐,生产环境)
|
### 使用 systemd(推荐,生产环境)
|
||||||
|
|||||||
23
monitor.py
23
monitor.py
@@ -26,6 +26,11 @@ from email.mime.multipart import MIMEMultipart
|
|||||||
from typing import Optional, Dict
|
from typing import Optional, Dict
|
||||||
import signal
|
import signal
|
||||||
|
|
||||||
|
# 数据目录(用于日志和运行时文件)
|
||||||
|
_DEFAULT_DATA_DIR = Path(__file__).parent.resolve()
|
||||||
|
DATA_DIR = Path(os.environ.get('GPA_DATA_DIR', str(_DEFAULT_DATA_DIR))).expanduser()
|
||||||
|
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# 配置日志
|
# 配置日志
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -40,7 +45,7 @@ if not logger.handlers:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 文件处理器
|
# 文件处理器
|
||||||
file_handler = logging.FileHandler('monitor.log', encoding='utf-8')
|
file_handler = logging.FileHandler(DATA_DIR / 'monitor.log', encoding='utf-8')
|
||||||
file_handler.setFormatter(formatter)
|
file_handler.setFormatter(formatter)
|
||||||
logger.addHandler(file_handler)
|
logger.addHandler(file_handler)
|
||||||
|
|
||||||
@@ -67,10 +72,10 @@ class GradeMonitor:
|
|||||||
})
|
})
|
||||||
|
|
||||||
# 文件路径
|
# 文件路径
|
||||||
self.script_dir = Path(__file__).parent.absolute()
|
self.data_dir = DATA_DIR
|
||||||
self.last_grade_file = self.script_dir / '.last_grade_hash.txt'
|
self.last_grade_file = self.data_dir / '.last_grade_hash.txt'
|
||||||
self.last_grade_html_file = self.script_dir / '.last_grade_page.html'
|
self.last_grade_html_file = self.data_dir / '.last_grade_page.html'
|
||||||
self.last_grade_content_file = self.script_dir / '.last_grade_content.txt'
|
self.last_grade_content_file = self.data_dir / '.last_grade_content.txt'
|
||||||
|
|
||||||
# 运行标志
|
# 运行标志
|
||||||
self.running = True
|
self.running = True
|
||||||
@@ -362,7 +367,7 @@ class GradeMonitor:
|
|||||||
if not result:
|
if not result:
|
||||||
logger.warning("未能提取到成绩信息,页面可能结构异常")
|
logger.warning("未能提取到成绩信息,页面可能结构异常")
|
||||||
# 保存HTML以便调试
|
# 保存HTML以便调试
|
||||||
debug_file = self.script_dir / 'debug_page.html'
|
debug_file = self.data_dir / 'debug_page.html'
|
||||||
debug_file.write_text(html, encoding='utf-8')
|
debug_file.write_text(html, encoding='utf-8')
|
||||||
logger.info(f"已保存HTML到 {debug_file} 供调试")
|
logger.info(f"已保存HTML到 {debug_file} 供调试")
|
||||||
|
|
||||||
@@ -469,7 +474,7 @@ class GradeMonitor:
|
|||||||
logger.info("=" * 60)
|
logger.info("=" * 60)
|
||||||
|
|
||||||
# 保存课程列表
|
# 保存课程列表
|
||||||
courses_file = self.script_dir / '.last_courses.txt'
|
courses_file = self.data_dir / '.last_courses.txt'
|
||||||
courses_file.write_text('\n'.join(current_courses), encoding='utf-8')
|
courses_file.write_text('\n'.join(current_courses), encoding='utf-8')
|
||||||
|
|
||||||
# 计算哈希
|
# 计算哈希
|
||||||
@@ -478,7 +483,7 @@ class GradeMonitor:
|
|||||||
return (False, [])
|
return (False, [])
|
||||||
|
|
||||||
# 读取上次的课程列表
|
# 读取上次的课程列表
|
||||||
courses_file = self.script_dir / '.last_courses.txt'
|
courses_file = self.data_dir / '.last_courses.txt'
|
||||||
if courses_file.exists():
|
if courses_file.exists():
|
||||||
last_courses = courses_file.read_text(encoding='utf-8').strip().split('\n')
|
last_courses = courses_file.read_text(encoding='utf-8').strip().split('\n')
|
||||||
else:
|
else:
|
||||||
@@ -792,7 +797,7 @@ class GradeMonitor:
|
|||||||
# 如果解析失败(0门课程)且之前有课程,可能是临时问题
|
# 如果解析失败(0门课程)且之前有课程,可能是临时问题
|
||||||
if len(current_courses) == 0:
|
if len(current_courses) == 0:
|
||||||
# 检查是否之前有课程记录
|
# 检查是否之前有课程记录
|
||||||
courses_file = self.script_dir / '.last_courses.txt'
|
courses_file = self.data_dir / '.last_courses.txt'
|
||||||
if courses_file.exists():
|
if courses_file.exists():
|
||||||
try:
|
try:
|
||||||
previous_courses = courses_file.read_text(encoding='utf-8').strip().split('\n')
|
previous_courses = courses_file.read_text(encoding='utf-8').strip().split('\n')
|
||||||
|
|||||||
20
readme.md
20
readme.md
@@ -54,6 +54,24 @@ python3 monitor.py
|
|||||||
# 按 Ctrl+B 然后按 D 离开会话
|
# 按 Ctrl+B 然后按 D 离开会话
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Docker 部署(推荐)
|
||||||
|
|
||||||
|
> 运行日志和缓存文件会写入 `./data/`,配置文件挂载为只读。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1) 准备配置文件(同级目录下的 config.ini)
|
||||||
|
# 2) 启动
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
docker logs -f gpa-monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
**测试模式:**
|
||||||
|
```bash
|
||||||
|
docker compose run --rm gpa-monitor python /app/monitor.py --config /data/config.ini --test
|
||||||
|
```
|
||||||
|
|
||||||
## 功能特点
|
## 功能特点
|
||||||
|
|
||||||
✅ **智能检测** - 检测新增课程(而非简单的页面变化)
|
✅ **智能检测** - 检测新增课程(而非简单的页面变化)
|
||||||
@@ -193,4 +211,4 @@ tmux attach -t grade_monitor
|
|||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|||||||
164
私有Docker仓库部署手册.md
Normal file
164
私有Docker仓库部署手册.md
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
# **Debian 私有 Docker 仓库 (Registry \+ UI \+ HTTPS) 部署手册**
|
||||||
|
|
||||||
|
本文档详细说明了如何在 Debian 系统上构建一个支持域名访问、HTTPS 加密、用户认证以及图形化管理界面的私有 Docker 仓库。
|
||||||
|
|
||||||
|
## **1\. 基础环境准备**
|
||||||
|
|
||||||
|
### **1.1 系统更新与防火墙**
|
||||||
|
|
||||||
|
确保服务器已开启 80 (HTTP) 和 443 (HTTPS) 端口。
|
||||||
|
|
||||||
|
sudo apt update && sudo apt upgrade \-y
|
||||||
|
\# 如果开启了 ufw 防火墙
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
|
||||||
|
### **1.2 安装 Docker 与 Docker Compose**
|
||||||
|
|
||||||
|
使用 Docker 官方源安装最新版本。
|
||||||
|
|
||||||
|
sudo apt install ca-certificates curl gnupg lsb-release \-y
|
||||||
|
sudo install \-m 0755 \-d /etc/apt/keyrings
|
||||||
|
curl \-fsSL \[https://download.docker.com/linux/debian/gpg\](https://download.docker.com/linux/debian/gpg) | sudo gpg \--dearmor \-o /etc/apt/keyrings/docker.gpg
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||||
|
|
||||||
|
echo "deb \[arch=$(dpkg \--print-architecture) signed-by=/etc/apt/keyrings/docker.gpg\] \[https://download.docker.com/linux/debian\](https://download.docker.com/linux/debian) $(lsb\_release \-cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list \> /dev/null
|
||||||
|
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \-y
|
||||||
|
|
||||||
|
## **2\. 仓库服务配置 (Registry & UI)**
|
||||||
|
|
||||||
|
### **2.1 创建项目目录与认证文件**
|
||||||
|
|
||||||
|
我们将使用 htpasswd 为仓库添加登录限制。
|
||||||
|
|
||||||
|
mkdir \-p \~/docker-registry/auth && cd \~/docker-registry
|
||||||
|
|
||||||
|
\# 创建用户名为 admin,密码为 your\_password 的认证文件
|
||||||
|
\# 请务必修改下方的 your\_password
|
||||||
|
docker run \--entrypoint htpasswd httpd:2 \-Bbn admin your\_password \> auth/htpasswd
|
||||||
|
|
||||||
|
### **2.2 编写 docker-compose.yml**
|
||||||
|
|
||||||
|
该配置包含仓库核心服务和可视化 UI 服务。
|
||||||
|
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
registry:
|
||||||
|
image: registry:2
|
||||||
|
container\_name: registry-server
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
REGISTRY\_AUTH: htpasswd
|
||||||
|
REGISTRY\_AUTH\_HTPASSWD\_REALM: Registry Realm
|
||||||
|
REGISTRY\_AUTH\_HTPASSWD\_PATH: /auth/htpasswd
|
||||||
|
REGISTRY\_HTTP\_SECRET: some\_random\_secret
|
||||||
|
REGISTRY\_HTTP\_CORS\_ENABLED: "true"
|
||||||
|
REGISTRY\_HTTP\_CORS\_ALLOWEDMETHODS: "\[HEAD,GET,OPTIONS,DELETE\]"
|
||||||
|
REGISTRY\_HTTP\_CORS\_ALLOWEDORIGINS: "\['\[https://docker.aizhangz.top\](https://docker.aizhangz.top)'\]"
|
||||||
|
REGISTRY\_STORAGE\_DELETE\_ENABLED: "true"
|
||||||
|
volumes:
|
||||||
|
\- ./data:/var/lib/registry
|
||||||
|
\- ./auth:/auth
|
||||||
|
ports:
|
||||||
|
\- "127.0.0.1:5000:5000"
|
||||||
|
|
||||||
|
ui:
|
||||||
|
image: joxit/docker-registry-ui:latest
|
||||||
|
container\_name: registry-ui
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
\- REGISTRY\_TITLE=My Private Registry
|
||||||
|
\- NGINX\_PROXY\_PASS\_URL=http://registry:5000
|
||||||
|
\- SINGLE\_REGISTRY=true
|
||||||
|
\- DELETE\_IMAGES=true
|
||||||
|
ports:
|
||||||
|
\- "127.0.0.1:8080:80"
|
||||||
|
|
||||||
|
启动容器:
|
||||||
|
|
||||||
|
docker compose up \-d
|
||||||
|
|
||||||
|
## **3\. Nginx 反向代理与 SSL 证书**
|
||||||
|
|
||||||
|
### **3.1 安装 Nginx 与 Certbot**
|
||||||
|
|
||||||
|
sudo apt install nginx certbot python3-certbot-nginx \-y
|
||||||
|
|
||||||
|
### **3.2 申请证书**
|
||||||
|
|
||||||
|
\# 请将 docker.aizhangz.top 替换为您实际解析好的域名
|
||||||
|
sudo certbot \--nginx \-d docker.aizhangz.top
|
||||||
|
|
||||||
|
### **3.3 修改 Nginx 配置文件**
|
||||||
|
|
||||||
|
编辑 /etc/nginx/sites-available/default,将 HTTPS 核心块修改为如下代理逻辑。
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server\_name docker.aizhangz.top;
|
||||||
|
|
||||||
|
\# SSL 证书路径(由 Certbot 自动生成)
|
||||||
|
ssl\_certificate /etc/letsencrypt/live/docker.aizhangz.top/fullchain.pem;
|
||||||
|
ssl\_certificate\_key /etc/letsencrypt/live/docker.aizhangz.top/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl\_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
\# 允许上传大型镜像文件
|
||||||
|
client\_max\_body\_size 0;
|
||||||
|
chunked\_transfer\_encoding on;
|
||||||
|
|
||||||
|
\# 1\. 路由 Docker API 请求 (命令行操作及 UI 后台通讯)
|
||||||
|
location /v2/ {
|
||||||
|
proxy\_pass \[http://127.0.0.1:5000\](http://127.0.0.1:5000);
|
||||||
|
proxy\_set\_header Host $host;
|
||||||
|
proxy\_set\_header X-Real-IP $remote\_addr;
|
||||||
|
proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;
|
||||||
|
proxy\_set\_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy\_read\_timeout 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
\# 2\. 路由浏览器访问请求 (UI 界面)
|
||||||
|
location / {
|
||||||
|
proxy\_pass \[http://127.0.0.1:8080\](http://127.0.0.1:8080);
|
||||||
|
proxy\_set\_header Host $host;
|
||||||
|
proxy\_set\_header X-Real-IP $remote\_addr;
|
||||||
|
proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;
|
||||||
|
proxy\_set\_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
重启 Nginx:
|
||||||
|
|
||||||
|
sudo nginx \-t && sudo systemctl restart nginx
|
||||||
|
|
||||||
|
## **4\. 客户端使用指南**
|
||||||
|
|
||||||
|
### **4.1 登录仓库**
|
||||||
|
|
||||||
|
在任意客户端机器(Windows/Linux/Mac)执行:
|
||||||
|
|
||||||
|
docker login docker.aizhangz.top
|
||||||
|
\# 输入步骤 2.1 中设置的用户名(admin)和密码
|
||||||
|
|
||||||
|
### **4.2 推送镜像**
|
||||||
|
|
||||||
|
\# 以 busybox 为例
|
||||||
|
docker pull busybox
|
||||||
|
docker tag busybox docker.aizhangz.top/my-busybox:v1
|
||||||
|
docker push docker.aizhangz.top/my-busybox:v1
|
||||||
|
|
||||||
|
### **4.3 访问 Web 界面**
|
||||||
|
|
||||||
|
在浏览器打开:https://docker.aizhangz.top
|
||||||
|
|
||||||
|
输入账号密码后即可可视化管理镜像。
|
||||||
|
|
||||||
|
## **5\. 维护说明**
|
||||||
|
|
||||||
|
* **查看容器状态**:docker compose ps
|
||||||
|
* **查看日志**:docker compose logs \-f
|
||||||
|
* **证书续期**:Certbot 会自动处理,可手动测试:sudo certbot renew \--dry-run
|
||||||
|
* **存储位置**:所有镜像物理文件存储在 \~/docker-registry/data 目录下。
|
||||||
Reference in New Issue
Block a user