feat: 集成 OpenTofu + Ansible + Gitea CI/CD

- 重构项目目录结构
- 添加 OpenTofu 多云支持
- 配置 Ansible 自动化部署
- 集成 Gitea Actions CI/CD 流水线
- 添加 Docker Swarm 管理
- 完善监控和安全配置
This commit is contained in:
2025-09-20 10:48:41 +00:00
parent d755f237a0
commit 7eb4a33523
55 changed files with 3745 additions and 1921 deletions

View File

@@ -0,0 +1,166 @@
version: '3.8'
services:
# Web 应用示例
webapp:
image: nginx:alpine
networks:
- traefik-public
configs:
- source: webapp-html
target: /usr/share/nginx/html/index.html
deploy:
replicas: 2
labels:
- traefik.enable=true
- traefik.http.routers.webapp.rule=Host(`app.local`)
- traefik.http.routers.webapp.entrypoints=web
- traefik.http.services.webapp.loadbalancer.server.port=80
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
# API 服务示例
api:
image: httpd:alpine
networks:
- traefik-public
configs:
- source: api-html
target: /usr/local/apache2/htdocs/index.html
deploy:
replicas: 2
labels:
- traefik.enable=true
- traefik.http.routers.api.rule=Host(`api.local`)
- traefik.http.routers.api.entrypoints=web
- traefik.http.services.api.loadbalancer.server.port=80
# 添加路径前缀
- traefik.http.routers.api-path.rule=Host(`app.local`) && PathPrefix(`/api`)
- traefik.http.routers.api-path.entrypoints=web
- traefik.http.routers.api-path.service=api
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
# 监控服务示例
monitor:
image: nginx:alpine
networks:
- traefik-public
configs:
- source: monitor-html
target: /usr/share/nginx/html/index.html
deploy:
replicas: 1
labels:
- traefik.enable=true
- traefik.http.routers.monitor.rule=Host(`monitor.local`)
- traefik.http.routers.monitor.entrypoints=web
- traefik.http.services.monitor.loadbalancer.server.port=80
# 添加基本认证 (可选)
- traefik.http.routers.monitor.middlewares=auth
- traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$10$$DLKjKQKQKQKQKQKQKQKQKe
restart_policy:
condition: on-failure
networks:
traefik-public:
external: true
configs:
webapp-html:
content: |
<!DOCTYPE html>
<html>
<head>
<title>Web App - Traefik Swarm Demo</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
.container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #2c3e50; }
.info { background: #e8f4fd; padding: 15px; border-radius: 4px; margin: 20px 0; }
</style>
</head>
<body>
<div class="container">
<h1>🚀 Web Application</h1>
<div class="info">
<p><strong>服务:</strong> webapp</p>
<p><strong>访问地址:</strong> http://app.local</p>
<p><strong>负载均衡:</strong> Traefik + Docker Swarm</p>
<p><strong>时间:</strong> <span id="time"></span></p>
</div>
<p>这是通过 Traefik 路由的 Web 应用示例。</p>
</div>
<script>
document.getElementById('time').textContent = new Date().toLocaleString();
</script>
</body>
</html>
api-html:
content: |
<!DOCTYPE html>
<html>
<head>
<title>API Service - Traefik Swarm Demo</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
.container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #27ae60; }
.info { background: #e8f8f5; padding: 15px; border-radius: 4px; margin: 20px 0; }
</style>
</head>
<body>
<div class="container">
<h1>🔌 API Service</h1>
<div class="info">
<p><strong>服务:</strong> api</p>
<p><strong>访问地址:</strong> http://api.local</p>
<p><strong>路径路由:</strong> http://app.local/api</p>
<p><strong>负载均衡:</strong> Traefik + Docker Swarm</p>
<p><strong>时间:</strong> <span id="time"></span></p>
</div>
<p>这是通过 Traefik 路由的 API 服务示例。</p>
</div>
<script>
document.getElementById('time').textContent = new Date().toLocaleString();
</script>
</body>
</html>
monitor-html:
content: |
<!DOCTYPE html>
<html>
<head>
<title>Monitor Service - Traefik Swarm Demo</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
.container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #e74c3c; }
.info { background: #fdf2e9; padding: 15px; border-radius: 4px; margin: 20px 0; }
</style>
</head>
<body>
<div class="container">
<h1>📊 Monitor Service</h1>
<div class="info">
<p><strong>服务:</strong> monitor</p>
<p><strong>访问地址:</strong> http://monitor.local</p>
<p><strong>认证:</strong> 基本认证保护</p>
<p><strong>负载均衡:</strong> Traefik + Docker Swarm</p>
<p><strong>时间:</strong> <span id="time"></span></p>
</div>
<p>这是通过 Traefik 路由的监控服务示例。</p>
</div>
<script>
document.getElementById('time').textContent = new Date().toLocaleString();
</script>
</body>
</html>

View File

@@ -0,0 +1,70 @@
version: '3.8'
services:
traefik:
image: traefik:v3.0
command:
# API 和 Dashboard
- --api.dashboard=true
- --api.insecure=true
# 入口点
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
# Docker Swarm Provider
- --providers.swarm=true
- --providers.swarm.endpoint=unix:///var/run/docker.sock
- --providers.swarm.exposedByDefault=false
- --providers.swarm.network=traefik-public
# 日志
- --log.level=INFO
- --accesslog=true
# 指标
- --metrics.prometheus=true
- --metrics.prometheus.addEntryPointsLabels=true
- --metrics.prometheus.addServicesLabels=true
# 证书解析器 (可选)
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.letsencrypt.acme.email=admin@example.com
- --certificatesresolvers.letsencrypt.acme.storage=/certificates/acme.json
ports:
- "80:80"
- "443:443"
- "8080:8080" # Dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik-certificates:/certificates
networks:
- traefik-public
deploy:
mode: global
placement:
constraints:
- node.role == manager
labels:
# Traefik Dashboard 路由
- traefik.enable=true
- traefik.http.routers.traefik-dashboard.rule=Host(`traefik.local`)
- traefik.http.routers.traefik-dashboard.service=api@internal
- traefik.http.services.traefik-dashboard.loadbalancer.server.port=8080
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
networks:
traefik-public:
external: true
volumes:
traefik-certificates: