
1. 为什么选 Drone CI 而不是 Jenkins一个轻量级 CI 工具的真实落地场景你是不是也经历过在一台 2 核 4G 的阿里云轻量应用服务器上刚docker-compose up -d启动 Jenkins还没配置完第一个流水线top一看 Java 进程已经占了 1.8G 内存Web 界面卡顿得像在拨号上网或者更糟——某天凌晨三点收到告警Jenkins Master 因为 GC 停顿太久被 Kubernetes 自动驱逐整个测试环境停摆两小时这不是段子是我去年在三个不同客户现场踩过的坑。而真正让我下定决心切换到Drone CI的转折点是一次给某电商 SaaS 初创团队做 DevOps 改造他们只有 1 台 2C4G 的 Ubuntu 22.04 云服务器要支撑 5 个前端项目 3 个 Node.js 微服务的每日构建、单元测试和镜像推送。Jenkins 方案预估需额外采购 1 台专用构建节点而 Drone CI 的完整部署含 PostgreSQL、Redis、Drone Server 和 Runner实测仅占用 680MB 内存CPU 峰值负载稳定在 35% 以内且所有组件通过单个docker-compose.yml管理——这才是“轻量级”该有的样子。Drone CI 的核心设计哲学是把 CI/CD 流水线彻底“右移”到代码仓库侧。它不自己维护庞大的插件生态和 UI 渲染引擎而是直接读取项目根目录下的.drone.yml文件YAML 格式将构建逻辑完全声明化、版本化。这意味着你的 CI 配置不再是 Jenkins 控制台里一堆点击勾选的抽象选项而是和package.json、Dockerfile一样受 Git 版本控制、可 Code Review、可复用、可回滚。比如一个 Vue 项目只需写 12 行 YAML 就能完成 lint → build → test → Docker 构建 → 推送私有镜像仓库的全流程而同等功能在 Jenkins 中往往需要安装 4 个插件、配置 7 处全局参数、编写 Groovy 脚本片段。这种极简主义不是偷懒而是把运维复杂度从“人肉操作”转移到“代码定义”让持续集成真正成为开发流程的自然延伸。更重要的是Drone 的架构天然适配现代云原生环境。它的 Server 组件只负责解析 YAML、调度任务、存储状态真正的构建工作全部由轻量级 Runner 承担——Runner 可以是 Docker-in-Docker 容器、Kubernetes Pod甚至物理机上的二进制进程。这种分离式设计让扩容变得极其简单当构建队列堆积时你不需要重启整个 CI 系统只需docker-compose scale runner3或在 K8s 中调整 ReplicaSet 数量。我曾在一个金融客户的生产环境中将 Runner 从 1 个水平扩展到 8 个整个过程对正在运行的流水线零影响而 Jenkins 在类似场景下往往需要停服升级插件或调整 JVM 参数。所以当你看到热搜词里反复出现 “docker compose restart always”、“docker安装部署”、“ubuntu安装docker compose”这背后反映的正是开发者对“开箱即用、弹性伸缩、资源可控”的真实渴求——Drone CI 正是为此而生。2. 本地部署 Drone CI 的完整技术栈与选型逻辑2.1 为什么必须用 Docker Compose 而非裸机安装先说结论在非生产环境或中小团队中Docker Compose 是部署 Drone CI 的唯一合理选择。原因非常实际Drone CI 依赖至少 3 个独立服务协同工作——ServerAPI 和 Web UI、Runner执行构建任务、Database存储构建历史、用户信息等。如果采用传统方式在 Ubuntu 上手动安装 PostgreSQL、配置 Redis 密码、编译 Drone Server 二进制、设置 systemd 服务、再为 Runner 编写独立的启动脚本……光是环境一致性就足以耗掉一整天。而 Docker Compose 的价值恰恰在于它把这种多服务依赖关系用一份声明式文件固化下来。你不需要记住pg_hba.conf怎么改、Redis 的requirepass字段在哪、Drone Server 的DRONE_DATABASE_DRIVER环境变量对应哪个驱动名——这些细节全部封装在docker-compose.yml的environment和volumes字段里。更重要的是Compose 的depends_on和健康检查机制能确保 PostgreSQL 完全就绪后才启动 Server避免因启动顺序错误导致的“数据库连接拒绝”这类低级故障。我见过太多团队在裸机部署失败后转头去折腾 Jenkins本质上不是 Jenkins 更强大而是它的“一键安装包”掩盖了底层复杂性。而 Drone 的设计理念是“透明”它要求你直面基础设施的每一个环节。Docker Compose 正好提供了这种透明性与便利性的平衡点你既能清晰看到每个容器的端口映射、卷挂载路径、环境变量又能用一条命令完成整套环境的启停、重建、日志查看。比如docker-compose logs -f server实时跟踪 Server 日志docker-compose exec runner sh进入 Runner 容器调试网络连通性——这些操作在裸机环境下需要分别登录不同服务、查找日志路径、切换用户权限效率相差数倍。2.2 数据库选型PostgreSQL vs SQLite 的硬核对比Drone CI 官方支持 SQLite、PostgreSQL、MySQL 三种数据库后端。但如果你计划长期使用、需要团队协作、或未来可能接入 LDAP/OAuth 认证PostgreSQL 是唯一值得考虑的选择。SQLite 虽然开箱即用无需单独部署数据库服务但它本质是一个嵌入式文件数据库所有读写操作都锁定整个drone.db文件。当多个构建任务并发执行时你会频繁遇到database is locked错误构建日志里满屏都是failed to acquire database lock。我在一个 10 人前端团队的测试环境中实测过当同时触发 3 个 PR 构建时SQLite 的平均构建延迟从 8 秒飙升至 42 秒且失败率高达 37%。而换成 PostgreSQL 后同样负载下延迟稳定在 9~11 秒失败率为 0。PostgreSQL 的优势远不止于并发性能。它的 WALWrite-Ahead Logging机制保证了数据强一致性即使服务器意外断电重启后数据库也能自动恢复到最近一次事务提交的状态不会丢失任何构建记录。更重要的是PostgreSQL 提供成熟的备份方案pg_dump可以在不影响服务的情况下生成逻辑备份pg_basebackup支持热物理备份配合 WAL 归档还能实现 PITRPoint-in-Time Recovery——这意味着如果某天你不小心在 Drone UI 里误删了某个关键仓库的构建历史只要备份存在就能精确恢复到删除前一秒的状态。而 SQLite 的备份只能粗暴地cp drone.db drone.db.bak且备份期间无法写入新数据。对于一个承载着团队质量门禁的系统这种脆弱性是不可接受的。提示不要被“PostgreSQL 安装复杂”吓退。在 Docker Compose 中它只是一段 8 行的 YAMLdb: image: postgres:15-alpine environment: POSTGRES_DB: drone POSTGRES_USER: drone POSTGRES_PASSWORD: your_strong_password volumes: - ./postgres-data:/var/lib/postgresql/data restart: unless-stopped这比在 Ubuntu 上手动执行apt install postgresql、sudo -u postgres psql、CREATE DATABASE drone;等 12 步操作不知简洁多少倍。2.3 Runner 类型抉择Docker Runner vs Exec Runner 的实战权衡Drone Runner 是真正干活的“工人”目前主流有 Docker Runner推荐和 Exec Runner 两种。Docker Runner 的核心能力是为每个构建任务动态创建一个全新的 Docker 容器并在其中执行.drone.yml定义的步骤。这带来了两个决定性优势环境隔离和资源可控。比如你的 Python 项目需要 Python 3.9而另一个 Go 项目需要 Go 1.21Docker Runner 可以为它们分别拉取python:3.9-slim和golang:1.21-alpine镜像互不干扰。而 Exec Runner 是在宿主机上直接执行命令所有项目共享同一套系统环境极易因 Python 版本冲突、全局 npm 包污染等问题导致构建失败。资源可控则体现在内存和 CPU 限制上。Docker Runner 允许你在.drone.yml中为每个步骤精确指定memory_limit和cpus例如- name: build image: node:18-alpine memory_limit: 1g cpus: 1.0 commands: - npm ci - npm run build这样即使某个构建脚本意外进入死循环它最多只能耗尽 1GB 内存和 1 个 CPU 核心不会拖垮整台服务器。而 Exec Runner 没有这种沙箱机制一个失控的while true; do echo 1; done就能让服务器假死。当然Docker Runner 也有代价它需要宿主机开启docker.sock挂载这带来了一定的安全风险。但只要你遵循最小权限原则——Runner 容器只挂载/var/run/docker.sock不挂载/或/etc且不赋予--privileged权限——风险是完全可控的。事实上GitHub Actions 的 self-hosted runner、GitLab Runner 的 docker executor都采用相同的设计模式其安全性已得到大规模验证。3. 从零开始Docker Compose 部署 Drone CI 的逐行详解3.1 准备工作系统环境与前置依赖确认在动手写docker-compose.yml之前必须确保宿主机满足最低要求。这不是形式主义而是避免后续 90% 的“部署失败”问题的根源。首先确认 Docker Engine 版本不低于 20.10docker --version因为 Drone v2.14 使用了较新的容器运行时特性。其次检查 Docker Compose 版本必须使用 Compose V2即docker compose命令而非旧版docker-compose。你可以通过docker compose version验证输出应为Docker Compose version v2.x.x。如果显示Command docker-compose not found或版本低于 v2.10请立即升级——旧版 Compose 对profiles、healthcheck等关键字段支持不完善会导致 Runner 无法正确注册。接着为数据持久化创建必要目录。Drone 需要存储数据库文件、Runner 的缓存如 npm/yarn 包、以及 Server 的密钥。我习惯在/opt/drone下建立结构化目录sudo mkdir -p /opt/drone/{postgres-data,runner-cache,server-data} sudo chown -R $USER:$USER /opt/drone这里有个关键细节/opt/drone/runner-cache目录的权限必须是755且属主为当前用户非 root。因为 Runner 容器会以非 root 用户UID 1001运行如果目录属主是 root容器将无法写入缓存导致每次构建都重新下载 npm 包极大拖慢速度。这个坑我踩过三次每次都要重装环境才能发现。最后生成 Drone Server 的加密密钥。这是整个系统安全的基石用于加密数据库中的敏感信息如 OAuth token。执行openssl rand -hex 16复制输出的 32 位十六进制字符串它将作为DRONE_SECRET环境变量的值。请务必妥善保存一旦丢失所有已加密的凭证将无法解密只能重置整个 Drone 系统。3.2 核心配置文件docker-compose.yml 的每一行都经过生产验证下面这份docker-compose.yml是我在 7 个不同客户环境Ubuntu 20.04/22.04、CentOS 7/8、Debian 11中反复打磨、100% 可用的配置。它不是官方文档的简单搬运而是融合了大量实战经验的“抄作业”模板version: 3.8 services: # PostgreSQL 数据库服务 db: image: postgres:15-alpine environment: POSTGRES_DB: drone POSTGRES_USER: drone POSTGRES_PASSWORD: your_db_password_here # 替换为强密码 volumes: - /opt/drone/postgres-data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U drone -d drone] interval: 30s timeout: 10s retries: 5 restart: unless-stopped # Redis 缓存服务可选但强烈推荐 redis: image: redis:7-alpine command: redis-server --save 60 1 --loglevel warning volumes: - /opt/drone/redis-data:/data healthcheck: test: [CMD, redis-cli, ping] interval: 30s timeout: 10s retries: 5 restart: unless-stopped # Drone Server 主服务 server: image: drone/drone:2.14.0 ports: - 8000:80 # HTTP 访问端口后续将反向代理到域名 - 8080:443 # HTTPS 端口同上 volumes: - /opt/drone/server-data:/data - /var/run/docker.sock:/var/run/docker.sock # 必须挂载供 Runner 调用 environment: DRONE_SERVER_HOST: your-domain.com # 替换为你的域名如无域名填服务器IP DRONE_SERVER_PROTO: https # 强制使用 HTTPS即使本地测试也建议 DRONE_DATABASE_DRIVER: postgres DRONE_DATABASE_CONFIG: postgres://drone:your_db_password_heredb:5432/drone?sslmodedisable DRONE_RPC_SECRET: your_rpc_secret_here # 与 Runner 的 DRONE_RPC_SECRET 一致 DRONE_SECRET: your_encryption_secret_here # 即前面 openssl 生成的密钥 DRONE_GITHUB_CLIENT_ID: your_github_client_id # GitHub OAuth App ID DRONE_GITHUB_CLIENT_SECRET: your_github_client_secret # GitHub OAuth App Secret DRONE_USER_CREATE: username:admin,admin:true # 创建初始管理员账号 DRONE_LOGS_DEBUG: false DRONE_LOGS_TEXT: true DRONE_LOGS_PRETTY: true depends_on: db: condition: service_healthy redis: condition: service_healthy restart: unless-stopped # Docker Runner 服务 runner: image: drone/drone-runner-docker:1.12.0 volumes: - /var/run/docker.sock:/var/run/docker.sock - /opt/drone/runner-cache:/drone/cache - /tmp:/tmp environment: DRONE_RPC_HOST: server DRONE_RPC_PROTO: http DRONE_RPC_SECRET: your_rpc_secret_here # 必须与 server 的 DRONE_RPC_SECRET 完全一致 DRONE_RUNNER_CAPACITY: 4 # 最大并发构建任务数 DRONE_RUNNER_NAME: docker-runner-01 DRONE_RUNNER_NETWORKS: drone_default # 确保与 server 在同一 Docker 网络 DRONE_DOCKER_PRIVILEGED: false # 关键禁止特权模式提升安全性 DRONE_DOCKER_NETWORKS: drone_default DRONE_DOCKER_VOLUMES: /opt/drone/runner-cache:/drone/cache depends_on: server: condition: service_healthy restart: unless-stopped这份配置的关键点解析healthcheck的深度应用不仅为db和redis设置了健康检查更通过depends_on的condition: service_healthy强制server必须等待数据库完全就绪pg_isready返回成功后才启动。这避免了 Server 启动时因数据库未 ready 而疯狂重试、打满日志的常见故障。DRONE_SERVER_PROTO: https的强制设定即使你本地没有 SSL 证书也必须设为https。因为 Drone 的 OAuth 流程如 GitHub 登录严格要求重定向 URI 使用 HTTPS。若设为http用户点击登录按钮后会跳转到http://...而 GitHub 会拒绝该不安全的回调地址导致认证失败。解决方案是后续用 Nginx 反向代理并配置 Lets Encrypt 证书Server 本身只处理内部 HTTP 流量。DRONE_USER_CREATE的初始化技巧username:admin,admin:true不仅创建用户名为admin的用户更将其设为系统管理员admin:true。这是最简单的初始账号创建方式避免了首次访问时需要手动执行drone user add命令的麻烦。DRONE_DOCKER_PRIVILEGED: false的安全底线这是 Runner 安全配置的黄金法则。privileged模式等于把宿主机的 root 权限交给容器一旦 Runner 被攻破攻击者可直接控制整个服务器。Drone 的 Docker Runner 在非特权模式下通过docker.sock挂载已能完成 99% 的构建任务包括构建镜像、运行容器完全没有启用特权的必要。3.3 启动与首次访问绕过那些“页面打不开”的玄学问题执行docker-compose up -d后不要立刻打开浏览器。先用命令确认所有服务是否健康docker-compose ps # 输出应为 # NAME COMMAND SERVICE STATUS PORTS # drone-db-1 docker-entrypoint.s… db healthy (health: starting) ... # drone-redis-1 docker-entrypoint.s… redis healthy (health: starting) ... # drone-server-1 /bin/drone-server server healthy (health: starting) ... # drone-runner-1 /bin/drone-runner-d… runner healthy (health: starting) ...注意STATUS列必须显示healthy而非starting或unhealthy。如果卡在starting执行docker-compose logs db查看数据库日志大概率是POSTGRES_PASSWORD配置错误或volumes路径权限不对。当所有服务状态为healthy后访问http://your-server-ip:8000。此时你可能会遇到“无法连接”或“空白页”。别慌这通常有两个原因防火墙拦截Ubuntu 默认启用ufw需放行端口sudo ufw allow 8000 sudo ufw allow 8080Drone Server 的DRONE_SERVER_HOST配置错误这个值必须是你浏览器地址栏中输入的完整域名或 IP。例如如果你用http://192.168.1.100:8000访问那么DRONE_SERVER_HOST必须是192.168.1.100如果你用http://ci.yourcompany.com:8000访问那么DRONE_SERVER_HOST必须是ci.yourcompany.com。这个值会写入 Server 生成的 JavaScript 资源链接中如果填错前端会加载http://wrong-host:8000/static/app.js并 404导致页面白屏。首次访问时页面会跳转到 GitHub OAuth 授权页。你需要提前在 GitHub 创建一个 OAuth App访问https://github.com/settings/apps/newApplication name: 填Drone CIHomepage URL:https://your-domain.com与DRONE_SERVER_HOST一致Authorization callback URL:https://your-domain.com/login注意是/login不是/oauth)创建后将生成的Client ID和Client Secret填入docker-compose.yml的对应位置。授权成功后你将以admin身份登录首页会提示“没有仓库”。这时点击右上角头像 →Account→Activate Repository搜索你的 GitHub 仓库并激活。Drone 会自动为该仓库创建 Webhook后续 Push 或 PR 触发时Server 就能接收到事件并调度 Runner 执行构建。4. 实现外部访问Nginx 反向代理 Lets Encrypt 的零成本方案4.1 为什么不能直接暴露 8000 端口HTTP/HTTPS 混合的致命陷阱很多新手会想“我的服务器有公网 IP直接http://ip:8000不就能外网访问了吗” 这在技术上可行但会引发一系列连锁故障最终让你放弃 Drone。根本原因在于OAuth 认证协议对协议一致性的严苛要求。当你在 GitHub OAuth App 中设置Authorization callback URL为http://ip:8000/login时GitHub 会严格校验请求来源的Origin头。而现代浏览器出于安全策略当页面从https://github.com发起跳转时Origin头会被设为https://github.com但你的 Drone Server 如果监听在http://ip:8000它收到的Origin是http://ip两者协议http vs https和域名ip vs github.com均不匹配GitHub 会直接拒绝回调返回403 Forbidden。更隐蔽的问题是Cookie 安全属性。Drone Server 生成的会话 Cookie 默认带有Secure标志要求仅通过 HTTPS 传输如果你用 HTTP 访问浏览器会拒绝发送该 Cookie导致登录态无法维持每次刷新页面都要求重新登录。这就是为什么官方文档反复强调DRONE_SERVER_PROTO: https——它不是可选项而是整个认证链路的基石。因此必须通过反向代理Nginx/Apache将外部 HTTPS 流量转换为内部 HTTP 流量转发给 Drone Server。这样对外是标准的https://ci.yourcompany.com对内是http://server:80完美规避了协议混用问题。4.2 Nginx 配置一行都不能错的生产级模板在/etc/nginx/sites-available/drone中创建以下配置假设你已安装 Nginxupstream drone_backend { server 127.0.0.1:8000; } server { listen 80; server_name ci.yourcompany.com; # 替换为你的域名 # Lets Encrypt ACME 挑战目录 location ^~ /.well-known/acme-challenge/ { default_type text/plain; root /var/www/letsencrypt; } # 所有 HTTP 请求重定向到 HTTPS location / { return 301 https://$server_name$request_uri; } } server { listen 443 ssl http2; server_name ci.yourcompany.com; # SSL 证书路径由 certbot 自动生成 ssl_certificate /etc/letsencrypt/live/ci.yourcompany.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ci.yourcompany.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/ci.yourcompany.com/chain.pem; # SSL 安全加固来自 Mozilla SSL Configuration Generator ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # Drone Server 的反向代理核心配置 location / { proxy_pass http://drone_backend; 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_set_header X-Frame-Options SAMEORIGIN; proxy_buffers 256 16k; proxy_buffer_size 16k; client_max_body_size 0; client_body_timeout 12; send_timeout 300; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; proxy_redirect off; } # WebSocket 支持用于实时构建日志流 location /ws { proxy_pass http://drone_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; 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; } }这份配置的精华在于X-Forwarded-Proto $scheme这是最关键的头。它告诉 Drone Server“外面来的请求是 HTTPS”Server 会据此生成正确的重定向 URL 和 Cookie 属性。没有这一行DRONE_SERVER_PROTO: https就是空谈。location /ws的 WebSocket 专门配置Drone 的构建日志是通过 WebSocket 实时推送的。普通proxy_pass不支持 WebSocket 协议升级必须显式配置Upgrade和Connection头否则日志页面会一直显示“Connecting…”。client_max_body_size 0禁用请求体大小限制。因为 Drone 的 Webhook 事件尤其是大型 PR可能携带大量 JSON 数据Nginx 默认 1MB 限制会导致 Webhook 接收失败表现为 GitHub 显示 “400 Bad Request”。启用配置后sudo ln -sf /etc/nginx/sites-available/drone /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx4.3 Lets Encrypt 证书自动化certbot 的三步到位法获取免费 SSL 证书最可靠的方式是 Certbot。在 Ubuntu 上sudo apt update sudo apt install certbot python3-certbot-nginx -y然后执行# 第一步创建 ACME 挑战目录 sudo mkdir -p /var/www/letsencrypt sudo chown -R $USER:$USER /var/www/letsencrypt # 第二步临时停用 Nginx用 certbot 的 standalone 模式申请证书 sudo systemctl stop nginx sudo certbot certonly --standalone -d ci.yourcompany.com --email your-emailexample.com # 第三步重启 Nginx证书已自动写入 /etc/letsencrypt/ sudo systemctl start nginx注意--standalone模式要求 80 端口空闲所以必须先停 Nginx。申请成功后Certbot 会自动生成证书文件并配置自动续期systemctl list-timers | grep certbot可查看定时任务。你无需再手动操作。现在访问https://ci.yourcompany.com你应该能看到 Drone 的登录页面。用 GitHub 账号登录后即可在Account→Activate Repository中激活你的项目仓库。至此一个安全、稳定、可外网访问的轻量级 CI 系统已部署完成。5. 常见问题排查与独家避坑指南那些文档里不会写的真相5.1 “Build failed: no matching files” —— .drone.yml 路径的隐形杀手这是新手遇到的第一道坎。你明明在项目根目录写了.drone.ymlPush 到 GitHub 后 Drone 却报错no matching files。根本原因在于Drone 默认只扫描仓库的默认分支通常是main或master的根目录。如果你的.drone.yml文件在develop分支或者放在了ci/.drone.yml子目录下Drone 就找不到它。解决方案有三确保文件在默认分支根目录这是最简单的方法。在 GitHub 仓库 Settings → Branches 中确认Default branch是你存放.drone.yml的分支。在 Drone UI 中手动指定配置路径进入Repository Settings→Configuration将Configuration Path改为ci/.drone.yml如果文件在子目录。在.drone.yml中显式声明分支在文件开头添加--- kind: pipeline type: docker name: default trigger: branch: - develop - main这样 Drone 就知道要在develop和main分支都查找该文件。5.2 “Error: Cannot connect to the Docker daemon” —— Runner 的权限迷宫当构建日志里出现Cannot connect to the Docker daemon说明 Runner 容器无法访问宿主机的 Docker 引擎。最常见的原因是docker.sock挂载路径错误。在docker-compose.yml中Runner 的volumes必须是volumes: - /var/run/docker.sock:/var/run/docker.sock而不是/var/run/docker.sock:/var/run/docker.sock:ro只读或/var/run/docker.sock:/tmp/docker.sock路径不一致。/var/run/docker.sock是 Docker Engine 默认的 Unix socket 路径任何改动都会导致连接失败。另一个隐藏原因是SELinux。如果你在 CentOS/RHEL 上部署SELinux 可能阻止容器访问docker.sock。临时关闭验证sudo setenforce 0如果问题消失说明是 SELinux 策略问题。永久解决需添加策略sudo semanage fcontext -a -t container_file_t /var/run/docker\.sock sudo restorecon -v /var/run/docker.sock5.3 “Build stuck at ‘cloning’” —— Git Clone 超时的网络真相构建卡在Cloning into /drone/src...几小时不动。这通常不是 Drone 的问题而是Runner 容器的 DNS 解析失败。Docker 默认使用宿主机的/etc/resolv.conf但如果宿主机 DNS 配置不佳如指向了不可靠的公共 DNSRunner 内部的git clone就会超时。解决方案是在docker-compose.yml的runner服务中显式指定可靠的 DNSrunner: # ... 其他配置 dns: - 8.8.8.8 - 114.114.114.114或者更彻底地在宿主机的 Docker daemon 配置中全局设置/etc/docker/daemon.json{ dns: [8.8.8.8, 114.114.114.114] }然后sudo systemctl restart docker。5.4 “Runner not connected” —— RPC 秘钥不匹配的静默故障在 Drone UI 的Settings→Runners页面你看到 Runner 状态是offline但docker-compose logs runner里没有任何错误。这几乎 100% 是DRONE_RPC_SECRET不匹配造成的。Server 和 Runner 必须使用完全相同的密钥字符串一个字符都不能差。检查方法# 查看 Server 容器的环境变量 docker-compose exec server env | grep DRONE_RPC_SECRET # 查看 Runner 容器的环境变量 docker-compose exec runner env | grep DRONE_RPC_SECRET如果两者输出不一致修改docker-compose.yml确保server和runner的DRONE_RPC_SECRET值完全相同然后docker-compose up -d --force-recreate runner。实操心得我习惯把所有密钥DRONE_SECRET,DRONE_RPC_SECRET,POSTGRES_PASSWORD集中写在一个.env文件中docker-compose.yml通过${VAR_NAME}引用。这样修改一处全局生效杜绝手误。5.5 “Build succeeded but no Docker image pushed” —— 镜像仓库认证的终极解法.drone.yml中写了docker push但构建日志显示denied: requested access to the resource is denied。这是因为 Drone Runner 容器内没有 Docker Registry 的登录凭据。解决方案不是在 Runner 容器里docker login那只是临时的而是使用 Drone 的Docker Plugin它能在构建过程中自动注入凭据- name: publish image: plugins/docker settings: registry: your-registry.com repo: your-registry.com/your-namespace/your-app tags: ${DRONE_COMMIT_SHA:0:7} username: from_secret: docker_username password: from_secret: docker_password然后在 Drone UI 的Repository Settings→Secrets中添加两个密钥docker_username: 你的镜像仓库用户名docker_password: 你的镜像仓库密码或 Token这样Plugin 会在构建时安全地将凭据注入到docker login命令中无需在 YAML 中硬编码密码也无需在