Drone CI is a lightweight, container-native continuous integration platform that runs every pipeline step inside an isolated Docker container. Its pipeline definition lives entirely in a .drone.yml file committed alongside your source code, making pipelines version-controlled and reproducible by default. In this tutorial you will install Docker CE on RHEL 8, deploy a Drone Server connected to GitHub OAuth, deploy a Drone Docker Runner, write your first .drone.yml pipeline, and connect a GitHub repository to start running automated builds.
Prerequisites
- RHEL 8 server with a public IP or domain name (Drone Server requires an externally reachable callback URL for OAuth)
- sudo privileges on the server
- A GitHub account with permissions to register an OAuth application
- Port 80 (or 443 for TLS) open in the firewall
- Basic Docker familiarity
Step 1 — Install Docker CE on RHEL 8
RHEL 8 does not ship Docker CE in its default repositories. Add the official Docker repository and install the engine.
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable --now docker
# Allow your user to run Docker without sudo
sudo usermod -aG docker $USER
newgrp docker
docker --version
Step 2 — Register a GitHub OAuth Application
Drone uses GitHub OAuth to authenticate users and receive webhook events. Create the OAuth app in your GitHub account settings before starting the server.
# Navigate in your browser to:
# GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
#
# Fill in the fields:
# Application name: Drone CI
# Homepage URL: http://YOUR_SERVER_IP
# Authorization callback URL: http://YOUR_SERVER_IP/login
#
# After saving, GitHub shows you:
# Client ID: (copy this → DRONE_GITHUB_CLIENT_ID)
# Client Secret: (generate and copy → DRONE_GITHUB_CLIENT_SECRET)
#
# Also generate a shared secret for Drone internal RPC:
openssl rand -hex 16
# Save the output → DRONE_RPC_SECRET
Step 3 — Run the Drone Server Container
The Drone Server handles the web UI, user authentication, repository syncing, and pipeline orchestration. Run it as a Docker container, passing all configuration via environment variables.
docker run
--volume=/var/lib/drone:/data
--env=DRONE_GITHUB_CLIENT_ID=YOUR_CLIENT_ID
--env=DRONE_GITHUB_CLIENT_SECRET=YOUR_CLIENT_SECRET
--env=DRONE_RPC_SECRET=YOUR_RPC_SECRET
--env=DRONE_SERVER_HOST=YOUR_SERVER_IP
--env=DRONE_SERVER_PROTO=http
--env=DRONE_LOGS_PRETTY=true
--env=DRONE_LOGS_COLOR=true
--publish=80:80
--publish=443:443
--restart=always
--detach=true
--name=drone
drone/drone:2
# Verify the server is running
docker ps
docker logs drone
Open http://YOUR_SERVER_IP in a browser. You should be redirected to GitHub for authorization. After approving, you land on the Drone dashboard.
Step 4 — Run the Drone Docker Runner
The Drone Runner polls the server for pending pipeline jobs and executes each step inside a Docker container. It needs access to the host Docker socket so it can spawn step containers.
docker run
--volume=/var/run/docker.sock:/var/run/docker.sock
--env=DRONE_RPC_PROTO=http
--env=DRONE_RPC_HOST=YOUR_SERVER_IP
--env=DRONE_RPC_SECRET=YOUR_RPC_SECRET
--env=DRONE_RUNNER_CAPACITY=2
--env=DRONE_RUNNER_NAME=rhel8-runner
--publish=3000:3000
--restart=always
--detach=true
--name=drone-runner
drone/drone-runner-docker:1
# Confirm the runner connected to the server
docker logs drone-runner | grep "successfully pinged"
Step 5 — Write a .drone.yml Pipeline
The .drone.yml file lives at the root of your repository. Each step runs inside its own Docker container; steps share the workspace volume so artifacts from one step are available to the next.
cat > .drone.yml << 'EOF'
kind: pipeline
type: docker
name: default
steps:
- name: install-deps
image: python:3.11-slim
commands:
- pip install -r requirements.txt
- name: lint
image: python:3.11-slim
commands:
- pip install flake8
- flake8 src/
- name: test
image: python:3.11-slim
commands:
- pip install -r requirements.txt
- python -m pytest tests/ -v
- name: build-image
image: plugins/docker
settings:
repo: YOUR_DOCKERHUB_USERNAME/myapp
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8}
username:
from_secret: docker_username
password:
from_secret: docker_password
trigger:
branch:
- main
EOF
Step 6 — Activate the Repository and Trigger a Build
Activate the repository in the Drone UI so Drone registers a webhook on GitHub. Then push a commit to trigger the pipeline.
# In the Drone web UI:
# 1. Click "Sync" to refresh your repository list from GitHub
# 2. Find your repository and click "Activate"
# 3. Add secrets (docker_username, docker_password) under Repository → Settings → Secrets
# From your workstation — commit and push the pipeline file
git add .drone.yml
git commit -m "ci: add Drone pipeline"
git push origin main
# Watch the build in the Drone UI at http://YOUR_SERVER_IP
# Or tail the runner logs
docker logs -f drone-runner
Conclusion
You have installed Docker CE on RHEL 8, deployed a Drone Server and Docker Runner as containers, connected them to a GitHub OAuth application, and defined a complete CI/CD pipeline in a .drone.yml file that installs dependencies, lints, tests, and builds a Docker image on every push to main. Because every pipeline step runs inside a dedicated Docker container, builds are fully isolated, reproducible, and easy to debug locally by running the same images by hand. The entire Drone stack — server, runner, and pipelines — is defined in code and can be version-controlled alongside your application.
Next steps: Adding TLS to Drone CI with Let’s Encrypt on RHEL 8, Configuring Drone CI with Gitea for a Fully Self-Hosted Git and CI Stack, and Publishing Test Coverage Reports from Drone CI Pipelines.