基于Docker Compose构建个人私有云:从Gitea到Drone CI的全栈实践
1. 项目概述:从“大机架”到个人数字基础设施的构建
最近在GitHub上看到一个挺有意思的项目,叫
bigrack.dev
,作者是
baptiste-mnh
。光看这个名字,你可能会有点摸不着头脑——“大机架”?这到底是做什么的?点进去一看,发现它其实是一个个人化的、基于容器和自动化工具链的“数字基础设施”项目。简单来说,就是作者把自己日常开发、学习、甚至娱乐所用到的各种服务,比如代码仓库、文档Wiki、自动化构建、监控面板等等,全部打包、容器化,然后通过一套统一的编排和管理工具,部署在自己的服务器(或家庭服务器)上,形成一个完全由自己掌控的、私有的“开发与运维平台”。
这听起来是不是有点像自建一个小型的、功能齐全的“私有云”或“家庭实验室”?没错,其核心精神正是如此。在公有云服务无处不在的今天,为什么还要费劲自己搭建呢?
bigrack.dev
项目给出了几个很实在的理由:
完全的数据主权
(你的数据只在你自己的硬件上)、
极致的可定制性
(服务选型、配置、集成方式你说了算)、
深入的学习与实践
(从底层网络、存储到上层应用部署,全流程亲手操作),以及
长期的成本可控
(一次硬件投入,长期免服务费使用,尤其适合需要长期运行的服务)。这个项目非常适合那些对DevOps、SRE(站点可靠性工程)、家庭实验室(Homelab)感兴趣,或者单纯想拥有一个不受第三方约束的、高度集成的个人工作环境的开发者和技术爱好者。
2. 核心架构与设计哲学拆解
2.1 技术栈选型:为什么是它们?
bigrack.dev
的技术选型非常典型,代表了当前自托管领域的主流和最佳实践。理解这些选择背后的逻辑,比单纯记住工具名字更重要。
2.1.1 编排与部署层:Docker & Docker Compose
这是整个项目的基石。Docker提供了轻量级的容器化隔离,确保每个服务(如Gitea、Nextcloud、Prometheus)都运行在独立、可复现的环境中,避免了“在我的机器上能运行”的经典问题。Docker Compose则用于定义和运行多容器的应用。对于个人或小规模部署,Kubernetes(K8s)显得过于重型,而Docker Compose的YAML文件清晰定义了服务、网络、卷之间的关系,一键
docker-compose up -d
就能拉起整个栈,管理和维护的复杂度直线下降。这是平衡功能与复杂性的明智之选。
2.1.2 代码与协作核心:Gitea
为什么是Gitea而不是GitLab或自建Git?GitLab功能强大但资源消耗也大,对于个人服务器可能负担较重。Gitea是一个用Go编写的轻量级、开源Git服务,其设计目标就是快速、低消耗且易于安装。它完美覆盖了个人或小团队的代码托管、Pull Request、Issue跟踪等核心需求。在
bigrack.dev
的语境下,Gitea不仅是代码仓库,更是整个基础设施的“配置即代码”的存储中心,所有服务的Docker Compose文件、部署脚本、甚至这篇文档本身,都应该用Git管理起来。
2.1.3 自动化与CI/CD:Drone CI
有了代码仓库,自动化构建和部署(CI/CD)就是自然延伸。Drone CI是一个基于容器、声明式配置的轻量级CI/CD工具。它与Gitea(或GitHub、GitLab等)深度集成,通过项目根目录下的
.drone.yml
文件来定义流水线。当代码推送到Gitea的特定分支时,Drone会自动触发构建、测试、甚至自动部署到服务器。对于个人项目,这意味着你提交代码后,博客可以自动更新、Docker镜像可以自动构建并推送到私有仓库、服务可以自动滚动更新,极大地提升了效率。
2.1.4 监控与可观测性:Prometheus + Grafana
“可观测性”是现代运维的基石。Prometheus负责抓取和存储时间序列数据(如CPU使用率、内存占用、HTTP请求次数、服务健康状态)。Grafana则是一个强大的数据可视化平台,它从Prometheus读取数据,生成直观的仪表盘。在
bigrack.dev
中,你需要监控服务器的硬件资源、各个容器的运行状态、网络服务的可用性等。这套组合让你能一眼看清整个系统的健康状况,在问题影响用户体验前就发现端倪。
2.1.5 反向代理与入口管理:Traefik 或 Caddy
当你有多个Web服务(Gitea的Web界面、Grafana仪表盘、Nextcloud网盘等)运行在同一台服务器的不同端口时,你需要一个“总机接线员”——反向代理。它监听80和443端口,然后根据访问的域名(如
git.yourdomain.com
,
grafana.yourdomain.com
)将请求转发到对应的后端服务容器。Traefik和Caddy都是优秀的现代反向代理,它们最大的特点是能
自动发现容器
并配置路由,并与Let‘s Encrypt集成实现自动化的HTTPS证书申请和续签。这意味着你每新增一个带Web界面的服务,几乎不用手动修改代理配置,服务上线即带HTTPS。
2.2 设计模式:一切皆代码与不可变基础设施
bigrack.dev
项目隐含了两个重要的现代运维理念:
- 一切皆代码(Infrastructure as Code, IaC) :服务器配置、服务部署、网络设置都不再是手动在服务器上敲命令,而是通过Docker Compose文件、Drone流水线脚本等代码文件来定义。这些文件被保存在Git仓库中,可以进行版本控制、代码审查和回滚。要重建整个环境?只需一条命令。
- 不可变基础设施(Immutable Infrastructure) :一旦服务被部署,就不再直接登录容器去修改配置或更新应用。任何变更都通过更新代码(如Dockerfile或Compose文件中的镜像版本),然后触发CI/CD流程,构建新的镜像并替换旧容器来实现。这保证了环境的一致性和部署的可重复性。
3. 核心服务部署与配置实战
假设我们有一台安装了Ubuntu Server 22.04 LTS的物理机或虚拟机(至少4核CPU,8GB内存,100GB SSD存储),公网IP已配置,域名
yourdomain.com
已指向该IP。下面我们一步步搭建
bigrack.dev
的核心组件。
3.1 基础环境准备与Docker安装
首先,我们需要一个干净、安全的基础操作系统环境。
# 1. 更新系统并安装必要工具
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git vim htop net-tools
# 2. 安装Docker Engine(使用官方脚本)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# 3. 安装Docker Compose Plugin (Docker Compose V2)
sudo apt install -y docker-compose-plugin
# 4. 将当前用户加入docker组,避免每次使用sudo
sudo usermod -aG docker $USER
# 注意:需要退出当前终端重新登录,或执行 `newgrp docker` 使组权限生效
# 5. 验证安装
docker --version
docker compose version
注意 :生产环境务必遵循最小权限原则。如果服务器暴露在公网,需要配置防火墙(如
ufw),仅开放必要的端口(80, 443, 22),并考虑使用非root用户运行Docker守护进程,或使用sudo执行Docker命令。
3.2 编排核心:创建Docker Compose项目结构
我们将在
/opt/bigrack
目录下组织所有内容。清晰的目录结构是管理复杂Compose项目的关键。
sudo mkdir -p /opt/bigrack
sudo chown -R $USER:$USER /opt/bigrack
cd /opt/bigrack
# 创建核心目录结构
mkdir -p {data,configs,logs,scripts,backup}
mkdir -p data/{gitea,postgres,drone,nextcloud,prometheus,grafana}
mkdir -p configs/{traefik,caddy}
mkdir -p logs/{traefik,gitea}
现在,创建主
docker-compose.yml
文件。这里我们以
Traefik
作为反向代理为例。
# /opt/bigrack/docker-compose.yml
version: '3.8'
networks:
web:
external: true # 我们将手动创建这个网络,便于Traefik和其他服务通信
internal:
driver: bridge # 内部服务间通信网络
volumes:
gitea_data:
postgres_data:
drone_data:
nextcloud_data:
prometheus_data:
grafana_data:
traefik_certs:
services:
# 反向代理 - Traefik
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- web
- internal
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./configs/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
- ./configs/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
- traefik_certs:/etc/traefik/certs
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`traefik.yourdomain.com`)"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls=true"
- "traefik.http.routers.api.middlewares=auth"
# 为Traefik Dashboard添加基础认证(强烈建议!)
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$verylonghashedpassword"
# 数据库 - PostgreSQL (为Gitea, Drone等服务提供数据库)
postgres:
image: postgres:15-alpine
container_name: postgres
restart: unless-stopped
networks:
- internal
environment:
POSTGRES_USER: bigrack_admin
POSTGRES_PASSWORD: your_strong_postgres_password_here
POSTGRES_DB: bigrack
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U bigrack_admin"]
interval: 10s
timeout: 5s
retries: 5
# 代码托管 - Gitea
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
networks:
- internal
environment:
- USER_UID=1000
- USER_GID=1000
- DB_TYPE=postgres
- DB_HOST=postgres:5432
- DB_NAME=gitea
- DB_USER=bigrack_admin
- DB_PASSWD=your_strong_postgres_password_here
volumes:
- gitea_data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitea.rule=Host(`git.yourdomain.com`)"
- "traefik.http.routers.gitea.entrypoints=websecure"
- "traefik.http.routers.gitea.tls=true"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
# CI/CD - Drone Server
drone-server:
image: drone/drone:latest
container_name: drone-server
restart: unless-stopped
depends_on:
- gitea
networks:
- internal
environment:
- DRONE_GITEA_SERVER=https://git.yourdomain.com
- DRONE_GITEA_CLIENT_ID=your_gitea_oauth_client_id
- DRONE_GITEA_CLIENT_SECRET=your_gitea_oauth_client_secret
- DRONE_RPC_SECRET=your_strong_drone_rpc_secret_here
- DRONE_SERVER_HOST=drone.yourdomain.com
- DRONE_SERVER_PROTO=https
- DRONE_USER_CREATE=username:your_username,admin:true
volumes:
- drone_data:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.drone.rule=Host(`drone.yourdomain.com`)"
- "traefik.http.routers.drone.entrypoints=websecure"
- "traefik.http.routers.drone.tls=true"
- "traefik.http.services.drone-server.loadbalancer.server.port=80"
# Drone Runner (Docker Runner)
drone-runner:
image: drone/drone-runner-docker:latest
container_name: drone-runner
restart: unless-stopped
depends_on:
- drone-server
networks:
- internal
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_RPC_PROTO=https
- DRONE_RPC_HOST=drone-server
- DRONE_RPC_SECRET=your_strong_drone_rpc_secret_here
- DRONE_RUNNER_CAPACITY=2
- DRONE_RUNNER_NAME=bigrack-runner
# 监控 - Prometheus
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
networks:
- internal
volumes:
- prometheus_data:/prometheus
- ./configs/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=30d'
labels:
- "traefik.enable=true"
- "traefik.http.routers.prometheus.rule=Host(`prom.yourdomain.com`)"
- "traefik.http.routers.prometheus.entrypoints=websecure"
- "traefik.http.routers.prometheus.tls=true"
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
# 可视化 - Grafana
grafana:
image: grafana/grafana-oss:latest
container_name: grafana
restart: unless-stopped
depends_on:
- prometheus
networks:
- internal
environment:
- GF_SECURITY_ADMIN_PASSWORD=your_strong_grafana_admin_password
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- grafana_data:/var/lib/grafana
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=Host(`grafana.yourdomain.com`)"
- "traefik.http.routers.grafana.entrypoints=websecure"
- "traefik.http.routers.grafana.tls=true"
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
实操心得 :在编写Compose文件时,有几点至关重要:
- 密码管理 :永远不要将明文密码硬编码在Compose文件或代码中。上述示例仅为演示。在生产环境中,应使用Docker Secrets(在Swarm模式下)或通过环境变量文件(
.env)传入,并将.env文件加入.gitignore。更好的做法是使用如HashiCorp Vault等密钥管理工具。- 健康检查 :为数据库等关键服务配置
healthcheck,这样depends_on的condition: service_healthy才能生效,确保依赖服务真正就绪后再启动应用。- 标签(Labels) :Traefik通过Docker容器的Labels来动态配置路由。确保格式正确,特别是Host规则里的域名要和你实际拥有的域名一致。
- 网络隔离 :创建独立的
internal网络,让后端服务(如Gitea、PostgreSQL)不直接暴露在外部网络,只有Traefik能访问它们,提升安全性。
3.3 关键配置文件详解
光有Compose文件还不够,我们需要为Traefik、Prometheus等服务提供具体的配置。
3.3.1 Traefik 静态配置 (
traefik.yml
)
# /opt/bigrack/configs/traefik/traefik.yml
api:
dashboard: true
debug: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false # 非常重要!只有显式设置`traefik.enable=true`的容器才会被暴露
network: web
file:
filename: /etc/traefik/dynamic.yml
certificatesResolvers:
letsencrypt:
acme:
email: your-email@example.com # 替换为你的邮箱
storage: /etc/traefik/certs/acme.json
httpChallenge:
entryPoint: web
这个配置做了几件事:定义HTTP(80)和HTTPS(443)入口点;设置HTTP到HTTPS的自动重定向;配置Docker和文件作为配置提供者;设置Let‘s Encrypt作为证书解析器。
3.3.2 Traefik 动态配置 (
dynamic.yml
)
# /opt/bigrack/configs/traefik/dynamic.yml
http:
middlewares:
secHeaders:
headers:
browserXssFilter: true
contentTypeNosniff: true
frameDeny: true
sslRedirect: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
customFrameOptionsValue: "SAMEORIGIN"
routers:
# 可以为所有路由默认应用安全头中间件
# 在Compose文件的labels里引用:`traefik.http.routers.xxx.middlewares=secHeaders`
tls:
options:
default:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
动态配置通常用于定义公共的中间件(如安全头)和TLS选项,这些配置可以被多个路由复用。
3.3.3 Prometheus 配置 (
prometheus.yml
)
# /opt/bigrack/configs/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'docker'
static_configs:
- targets: ['host.docker.internal:9323'] # 需要启用Docker引擎的metrics接口
# 或者使用cAdvisor容器来收集容器指标
# - targets: ['cadvisor:8080']
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100'] # 需要部署node-exporter容器来收集主机指标
这个基础配置监控Prometheus自身。要监控Docker容器和主机节点,你需要额外部署
cAdvisor
和
node-exporter
容器,并将它们添加到targets中。
3.4 初始化与启动
在启动一切之前,我们需要创建外部网络并设置一些基础数据。
# 创建Traefik使用的共享网络
docker network create web
# 生成用于Traefik Dashboard的htpasswd密码
echo $(htpasswd -nb admin your_password) | sed -e s/\\$/\\$\\$/g
# 将输出(如 admin:$$apr1$$...)填入Compose文件中traefik的labels里。
# 进入项目目录
cd /opt/bigrack
# 启动所有服务(在后台运行)
docker compose up -d
# 查看所有容器状态
docker compose ps
# 跟踪日志(Ctrl+C退出)
docker compose logs -f
启动后,访问以下地址(将
yourdomain.com
替换为你的域名):
-
https://git.yourdomain.com:首次访问会进入Gitea安装页面。数据库主机填postgres:5432,其他信息根据Compose文件中的环境变量填写。 -
https://drone.yourdomain.com:用Gitea账号登录,完成Drone的OAuth配置。 -
https://grafana.yourdomain.com:默认账号admin,密码是你设置的GF_SECURITY_ADMIN_PASSWORD。首次登录后添加Prometheus(地址为http://prometheus:9090)作为数据源。 -
https://traefik.yourdomain.com:输入之前设置的基础认证账号密码,进入Traefik Dashboard,查看所有路由和服务状态。
4. 进阶集成与自动化工作流
基础服务跑起来只是开始,
bigrack.dev
的真正威力在于将这些服务串联成一个自动化的工作流。
4.1 配置Gitea与Drone的OAuth集成
这是打通代码托管和自动化的关键一步。
- 登录Gitea,点击右上角头像 -> 设置 -> 应用 。
- 点击 管理OAuth2应用程序 -> 创建新的OAuth2应用程序 。
-
应用名称填
Drone CI,重定向URI填https://drone.yourdomain.com/login(务必准确)。 - 点击创建,你会得到 客户端ID 和 客户端密钥 。
-
将这两个值分别填入
docker-compose.yml中drone-server服务的DRONE_GITEA_CLIENT_ID和DRONE_GITEA_CLIENT_SECRET环境变量。 -
重启Drone Server容器:
docker compose restart drone-server。 - 现在访问Drone,应该可以用Gitea账号登录并授权了。
4.2 创建你的第一个自动化流水线
假设你在Gitea上创建了一个名为
my-blog
的仓库,里面是一个静态博客(比如Hugo生成)。你可以通过Drone实现“提交代码 -> 自动构建 -> 自动部署”。
在博客项目根目录创建
.drone.yml
文件:
kind: pipeline
type: docker
name: build-and-deploy
steps:
- name: build-hugo
image: alpine:latest
commands:
- apk add hugo
- hugo --minify
- name: deploy-to-server
image: alpine:latest
environment:
SSH_KEY:
from_secret: ssh_private_key
commands:
- apk add openssh-client rsync
- mkdir -p ~/.ssh
- echo "$SSH_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H your-server-ip >> ~/.ssh/known_hosts
- rsync -avz --delete public/ user@your-server-ip:/var/www/myblog/
when:
branch:
- main
这个流水线做了两件事:
- 使用Hugo镜像构建静态网站。
-
通过SSH将生成的
public目录同步到服务器的Web目录。
关键点 :
-
from_secret: ssh_private_key:这里引用了Drone的一个密钥。你需要在Drone的Web界面中,进入my-blog仓库的设置(Settings -> Secrets),添加一个名为ssh_private_key的Secret,值是你的服务器SSH私钥。 切勿将私钥直接写在代码里! -
when: 指定了只有推送到main分支时才执行部署步骤。
在Gitea中提交并推送这个
.drone.yml
文件后,Drone会自动检测到并开始执行第一次构建。你可以在Drone的Web界面实时查看构建日志。
4.3 扩展服务:添加Nextcloud(私有云盘)
个人基础设施怎么能少了云盘?在
docker-compose.yml
的
services:
部分添加:
nextcloud:
image: nextcloud:latest
container_name: nextcloud
restart: unless-stopped
networks:
- internal
depends_on:
postgres:
condition: service_healthy
environment:
- POSTGRES_HOST=postgres
- POSTGRES_DB=nextcloud
- POSTGRES_USER=bigrack_admin
- POSTGRES_PASSWORD=your_strong_postgres_password_here
- NEXTCLOUD_ADMIN_USER=admin
- NEXTCLOUD_ADMIN_PASSWORD=your_strong_nextcloud_admin_password
volumes:
- nextcloud_data:/var/www/html
- ./data/nextcloud/apps:/var/www/html/custom_apps
- ./data/nextcloud/config:/var/www/html/config
- ./data/nextcloud/data:/var/www/html/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.rule=Host(`cloud.yourdomain.com`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
- "traefik.http.routers.nextcloud.tls=true"
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
然后运行
docker compose up -d nextcloud
即可启动。Traefik会自动为
cloud.yourdomain.com
配置HTTPS并路由到Nextcloud容器。
5. 运维、监控与故障排查实录
5.1 日常运维命令合集
掌握这些命令,管理你的
bigrack
会得心应手。
# 进入项目目录
cd /opt/bigrack
# 查看所有服务状态
docker compose ps
# 查看特定服务日志(如gitea)
docker compose logs gitea
# 实时跟踪日志
docker compose logs -f gitea
# 重启单个服务
docker compose restart gitea
# 更新所有服务到最新镜像(谨慎操作,最好先备份)
docker compose pull
docker compose up -d
# 进入容器内部执行命令(调试用)
docker compose exec gitea sh
# 备份所有数据卷(假设备份到/backup目录)
tar -czf /backup/bigrack-data-$(date +%Y%m%d).tar.gz ./data
# 查看资源使用情况
docker stats
# 清理未使用的镜像、容器、网络、卷(谨慎!)
docker system prune -a
5.2 监控告警配置
光有仪表盘不够,我们需要在出问题时收到通知。这里以Grafana Alerting配合邮件通知为例。
-
在Grafana中配置SMTP : 登录Grafana -> Administration -> Settings -> SMTP 。 填写你的邮件服务器信息(如Gmail SMTP,注意可能需要应用专用密码)。
Host: smtp.gmail.com:587 User: your-email@gmail.com Password: your-app-specific-password From Address: your-email@gmail.com点击
Send Test Email验证。 -
创建告警规则 : 进入Prometheus数据源的一个图表,比如“节点内存使用率”。点击图表标题 -> Edit -> Alert 。
-
Rule name
:
High Memory Usage -
Evaluate every
:
1m -
For
:
2m(持续2分钟触发才告警,避免抖动) -
Condition
:
WHEN max() OF query(A, 1m, now) IS ABOVE 0.85(内存使用率超过85%) - Notifications : 添加一个通知策略,关联你的邮箱。
-
Rule name
:
-
配置通知策略 : Grafana -> Alerting -> Notification policies 。 创建一个策略,匹配所有标签,设置默认联系点为你的邮箱。
现在,当服务器内存持续超过85%时,你就会收到告警邮件。
5.3 常见问题与排查技巧
问题1:Traefik Dashboard无法访问,或服务返回“404”或“Bad Gateway”。
-
检查点1:网络
。确保
traefik服务连接到了web和internal两个网络。docker network inspect web和docker network inspect internal查看容器是否在其中。 -
检查点2:标签
。确认服务的labels拼写正确,特别是
traefik.http.routers.xxx.rule=Host()中的域名。 -
检查点3:端口
。确认服务容器内部监听的端口(如Gitea是3000)与
traefik.http.services.xxx.loadbalancer.server.port一致。 -
检查点4:证书
。检查Traefik日志
docker compose logs traefik,看Let‘s Encrypt证书申请是否成功。首次访问可能需要几分钟申请证书。 -
排查命令
:
docker compose logs traefik查看路由发现和错误信息。
问题2:Drone无法触发构建。
- 检查点1:仓库激活 。登录Drone,确保目标仓库是“激活”状态(不是灰色)。
- 检查点2:Webhook 。在Gitea仓库设置里查看Webhook,Drone应该自动创建了一个。尝试手动推送(Redeliver),看Drone是否有日志。
-
检查点3:Runner状态
。
docker compose logs drone-runner查看Runner是否成功连接到Server。 -
检查点4:
.drone.yml语法 。使用在线YAML校验器检查语法,确保缩进正确。
问题3:Prometheus无法抓取指标或Grafana无法连接数据源。
-
检查点1:网络
。确保Prometheus、Grafana以及被监控目标(如node-exporter)在同一个Docker网络(通常是
internal)中。 -
检查点2:目标状态
。访问Prometheus的Targets页面 (
http://your-server-ip:9090/targets),查看抓取目标是否为UP。 -
检查点3:Grafana数据源配置
。在Grafana中检查Prometheus数据源的URL,在容器内应使用服务名
http://prometheus:9090,而不是localhost。
问题4:磁盘空间不足。 容器、镜像、日志和卷数据会占用大量空间。
-
查看占用
:
docker system df查看Docker资源使用情况。 -
清理无用镜像
:
docker image prune -a删除所有未被容器使用的镜像。 -
清理容器日志
:Docker的日志驱动默认是
json-file,日志会存储在/var/lib/docker/containers/。可以配置日志轮转,或在Compose文件中为服务添加日志限制:logging: driver: "json-file" options: max-size: "10m" max-file: "3" -
备份并清理数据卷
:定期备份重要数据卷(如
gitea_data,postgres_data)到其他存储介质,然后可以清理旧的、不必要的备份。
问题5:服务启动顺序导致依赖问题。
尽管Compose有
depends_on
,但它只控制容器启动顺序,不保证服务(如数据库)在应用启动前就“准备就绪”。
-
解决方案
:使用
condition: service_healthy(如示例中对PostgreSQL的依赖),并在依赖服务中配置有效的healthcheck。 - 备选方案 :在应用启动命令中加入等待脚本,例如在应用启动前执行一个循环,检查数据库端口是否可连接。
搭建和维护这样一个
bigrack.dev
式的个人基础设施,是一个持续迭代和学习的旅程。它不仅仅是一堆服务的集合,更是一个理解现代应用部署、网络、安全和自动化的绝佳实践场。从最基础的“服务能访问”,到“数据有备份”,再到“故障能自愈”、“变更可追溯”,每一步的深入都会带来新的挑战和收获。最关键的是,你拥有了一个完全受自己控制的数字基地,无论是用于严肃的项目开发,还是作为探索新技术的沙盒,它都提供了无与伦比的自由度和灵活性。
更多推荐
所有评论(0)