build docker image in ci

This commit is contained in:
Graham McIntire 2026-01-09 13:32:11 -06:00
parent 0f8cfc34e7
commit 5263175182
No known key found for this signature in database
5 changed files with 594 additions and 21 deletions

39
.gitignore vendored
View file

@ -1,25 +1,24 @@
# Created by https://gitignore.org
# Rust.gitignore
# Generated by Cargo
# will have compiled files and executables
debug
target
# These are backup files generated by rustfmt
# Rust
/target/
Cargo.lock
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# Generated by cargo mutants
# Contains mutation testing data
**/mutants.out*/
# Database files
*.db
*.db-shm
*.db-wal
# RustRover
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# Docker
data/
# OS
.DS_Store
Thumbs.db

138
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,138 @@
# GitLab CI/CD Configuration for Towerops Agent
# Builds and publishes Docker image to GitLab Container Registry
stages:
- test
- build
- release
variables:
# GitLab Container Registry
REGISTRY: registry.gitlab.com
IMAGE_NAME: graham/towerops-agent
# Docker BuildKit for better caching
DOCKER_BUILDKIT: 1
DOCKER_TLS_CERTDIR: "/certs"
# Test stage - compile and check code
test:
stage: test
image: rust:1.75-alpine
before_script:
- apk add --no-cache musl-dev
script:
- cargo check --release
- cargo fmt -- --check
- cargo clippy -- -D warnings
only:
- branches
- merge_requests
cache:
key: ${CI_COMMIT_REF_SLUG}-cargo
paths:
- target/
- .cargo/
# Build Docker image for branches (test build)
build:test:
stage: build
image: docker:24-dind
services:
- docker:24-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- |
docker build \
--tag $REGISTRY/$IMAGE_NAME:$CI_COMMIT_REF_SLUG \
--tag $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA \
.
- docker push $REGISTRY/$IMAGE_NAME:$CI_COMMIT_REF_SLUG
- docker push $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA
only:
- branches
except:
- main
- tags
# Build and push for main branch
build:main:
stage: build
image: docker:24-dind
services:
- docker:24-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- |
docker build \
--tag $REGISTRY/$IMAGE_NAME:latest \
--tag $REGISTRY/$IMAGE_NAME:main-$CI_COMMIT_SHORT_SHA \
.
- docker push $REGISTRY/$IMAGE_NAME:latest
- docker push $REGISTRY/$IMAGE_NAME:main-$CI_COMMIT_SHORT_SHA
- echo "IMAGE_TAG=latest" >> build.env
artifacts:
reports:
dotenv: build.env
only:
- main
# Release build for tags (versioned releases)
release:
stage: release
image: docker:24-dind
services:
- docker:24-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- |
# Extract version from tag (assumes tags like v0.1.0)
VERSION=${CI_COMMIT_TAG#v}
docker build \
--tag $REGISTRY/$IMAGE_NAME:$VERSION \
--tag $REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG \
--tag $REGISTRY/$IMAGE_NAME:latest \
.
docker push $REGISTRY/$IMAGE_NAME:$VERSION
docker push $REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG
docker push $REGISTRY/$IMAGE_NAME:latest
echo "Released version: $VERSION"
echo "IMAGE_TAG=$VERSION" >> release.env
artifacts:
reports:
dotenv: release.env
only:
- tags
except:
- branches
# Optional: Multi-architecture build (amd64 + arm64)
# Uncomment if you need ARM support (e.g., for Raspberry Pi)
#
# build:multiarch:
# stage: build
# image: docker:24-dind
# services:
# - docker:24-dind
# before_script:
# - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
# # Enable buildx for multi-arch
# - docker buildx create --use --name multiarch-builder
# - docker buildx inspect --bootstrap
# script:
# - |
# VERSION=${CI_COMMIT_TAG#v}
#
# docker buildx build \
# --platform linux/amd64,linux/arm64 \
# --tag $REGISTRY/$IMAGE_NAME:$VERSION \
# --tag $REGISTRY/$IMAGE_NAME:latest \
# --push \
# .
# only:
# - tags

387
DEPLOYMENT.md Normal file
View file

@ -0,0 +1,387 @@
# Towerops Agent - Deployment Guide
## GitLab CI/CD Pipeline
The agent uses GitLab CI/CD to automatically build and publish Docker images to the GitLab Container Registry.
### Pipeline Stages
1. **Test** - Compile, format check, and lint
2. **Build** - Build Docker image
3. **Release** - Tag and publish versioned releases
### Image Tags
| Git Action | Image Tags | Example |
|------------|------------|---------|
| Push to branch | `<branch>`, `<commit-sha>` | `feat-snmp`, `abc123` |
| Push to main | `latest`, `main-<sha>` | `latest`, `main-abc123` |
| Create tag | `<version>`, `<tag>`, `latest` | `0.1.0`, `v0.1.0`, `latest` |
### Registry Location
All images are pushed to:
```
registry.gitlab.com/graham/towerops-agent
```
## Creating a Release
### 1. Update Version
**In `Cargo.toml`**:
```toml
[package]
name = "towerops-agent"
version = "0.2.0" # ← Update this
edition = "2021"
```
### 2. Commit and Tag
```bash
git add Cargo.toml
git commit -m "Release v0.2.0"
git tag v0.2.0
git push origin main --tags
```
### 3. CI Pipeline Runs
GitLab CI will automatically:
- Run tests (cargo check, fmt, clippy)
- Build Docker image
- Tag as: `0.2.0`, `v0.2.0`, `latest`
- Push to registry
### 4. Verify Release
Check the Container Registry:
```
https://gitlab.com/graham/towerops-agent/container_registry
```
You should see:
- `latest` (updated)
- `0.2.0` (new)
- `v0.2.0` (new)
## Using the Images
### Pull Latest
```bash
docker pull registry.gitlab.com/graham/towerops-agent:latest
```
### Pull Specific Version
```bash
docker pull registry.gitlab.com/graham/towerops-agent:0.1.0
```
### Docker Compose
Update `docker-compose.yml`:
```yaml
services:
towerops-agent:
image: registry.gitlab.com/graham/towerops-agent:latest
# Or pin to specific version:
# image: registry.gitlab.com/graham/towerops-agent:0.1.0
environment:
- TOWEROPS_API_URL=https://app.towerops.com
- TOWEROPS_AGENT_TOKEN=${AGENT_TOKEN}
volumes:
- ./data:/data
```
## Customer Deployment
### Provide to Customers
**Option 1: Docker Compose (Recommended)**
Create `docker-compose.yml`:
```yaml
version: '3.8'
services:
towerops-agent:
image: registry.gitlab.com/graham/towerops-agent:latest
container_name: towerops-agent
restart: unless-stopped
environment:
- TOWEROPS_API_URL=https://app.towerops.com
- TOWEROPS_AGENT_TOKEN=<GET_FROM_UI>
volumes:
- ./data:/data
```
Instructions for customer:
```bash
# 1. Get agent token from Towerops UI
# 2. Replace <GET_FROM_UI> in docker-compose.yml
# 3. Start agent
docker-compose up -d
# 4. Check logs
docker-compose logs -f
# 5. Check status
docker-compose ps
```
**Option 2: Docker Run**
```bash
docker run -d \
--name towerops-agent \
--restart unless-stopped \
-e TOWEROPS_API_URL=https://app.towerops.com \
-e TOWEROPS_AGENT_TOKEN=<token> \
-v $(pwd)/data:/data \
registry.gitlab.com/graham/towerops-agent:latest
```
## CI/CD Configuration
### Required GitLab Variables
No additional CI/CD variables needed. GitLab provides these automatically:
- `CI_REGISTRY` - GitLab Container Registry URL
- `CI_REGISTRY_USER` - Username for registry login
- `CI_REGISTRY_PASSWORD` - Password for registry login
These are automatically available in all GitLab CI/CD pipelines.
### Pipeline Triggers
**Automatic**:
- Push to any branch → test + build with branch tag
- Push to main → test + build + tag as `latest`
- Create tag (e.g., `v0.1.0`) → test + build + release
**Manual**: No manual triggers configured (all automatic)
### Viewing Pipeline Status
1. Go to: https://gitlab.com/graham/towerops-agent/-/pipelines
2. Click on a pipeline to see detailed logs
3. Check job logs if build fails
## Local Development
### Build Locally
```bash
# Development build
cargo build
# Release build (optimized)
cargo build --release
# Build Docker image locally
docker build -t towerops-agent:local .
# Test local image
docker run --rm \
-e TOWEROPS_API_URL=http://host.docker.internal:4000 \
-e TOWEROPS_AGENT_TOKEN=test-token \
-v $(pwd)/test-data:/data \
towerops-agent:local
```
### Test Before Pushing
```bash
# Check compilation
cargo check --release
# Format check
cargo fmt -- --check
# Lint check
cargo clippy -- -D warnings
# All together (what CI runs)
cargo check --release && \
cargo fmt -- --check && \
cargo clippy -- -D warnings
```
## Rollback Procedure
### If Latest Version Has Issues
**Option 1: Revert Tag**
```bash
# Find previous working version
git tag -l
# Delete bad tag locally and remotely
git tag -d v0.2.0
git push origin :refs/tags/v0.2.0
# Customers can use previous version
docker pull registry.gitlab.com/graham/towerops-agent:0.1.0
```
**Option 2: Quick Fix**
```bash
# Fix the issue
git commit -m "Hotfix: fix critical bug"
# Create patch version
git tag v0.2.1
git push origin main --tags
# New pipeline builds v0.2.1 and updates latest
```
**Option 3: Pin Customers to Known Good Version**
Update customer docker-compose.yml:
```yaml
image: registry.gitlab.com/graham/towerops-agent:0.1.0 # Pin to working version
```
## Multi-Architecture Support (Optional)
To support ARM devices (Raspberry Pi, etc.), uncomment the multi-arch section in `.gitlab-ci.yml`.
This will build for:
- `linux/amd64` (x86_64 servers)
- `linux/arm64` (ARM servers, Raspberry Pi 4+)
**Note**: Multi-arch builds take longer (~2x build time).
## Monitoring Deployments
### Check Image Size
```bash
docker images registry.gitlab.com/graham/towerops-agent
```
Expected size: 10-20 MB
### Check Registry Usage
GitLab provides 10 GB of free registry storage. Monitor usage at:
```
https://gitlab.com/graham/towerops-agent/-/packages
```
### Cleanup Old Images
GitLab has automatic cleanup policies. Configure at:
```
Settings → Packages & Registries → Container Registry → Cleanup policies
```
Recommended settings:
- Keep most recent: 10 tags
- Keep tags matching: `^v\d+\.\d+\.\d+$` (versions)
- Remove tags older than: 90 days
## Troubleshooting
### Pipeline Fails at Test Stage
**Symptom**: `cargo check` or `cargo clippy` fails
**Fix**:
```bash
# Run locally to see errors
cargo check --release
cargo clippy -- -D warnings
# Fix issues and push
git add .
git commit -m "Fix clippy warnings"
git push
```
### Pipeline Fails at Build Stage
**Symptom**: Docker build fails
**Fix**:
```bash
# Test Docker build locally
docker build -t test .
# Check Dockerfile syntax
# Check .dockerignore isn't excluding needed files
```
### Image Too Large
**Symptom**: Image is >50 MB
**Fix**:
- Check release profile in Cargo.toml (should have `strip = true`)
- Verify multi-stage build is working
- Check for large files in context (review .dockerignore)
### Can't Pull Image
**Symptom**: `docker pull` fails with authentication error
**Fix**:
```bash
# Login to GitLab registry
docker login registry.gitlab.com
# Username: your GitLab username
# Password: personal access token with read_registry scope
# Or use deploy token (for customers)
# Create at: Settings → Repository → Deploy tokens
```
## Security
### Container Scanning (Optional)
Add to `.gitlab-ci.yml` for security scanning:
```yaml
include:
- template: Security/Container-Scanning.gitlab-ci.yml
container_scanning:
stage: test
variables:
CS_IMAGE: $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA
```
### Private Registry Access
For customers needing private access:
1. Create deploy token:
- Go to: Settings → Repository → Deploy tokens
- Name: `customer-deploy-token`
- Scopes: `read_registry`
- Copy username and token
2. Provide to customer:
```bash
docker login registry.gitlab.com
# Username: <deploy-token-username>
# Password: <deploy-token>
```
## Support
For issues with deployment:
1. Check pipeline logs in GitLab
2. Review CLAUDE.md for architecture details
3. Test locally with `docker build`
4. Check GitLab registry status page
---
**Last Updated**: January 9, 2026
**Registry**: registry.gitlab.com/graham/towerops-agent
**Current Version**: 0.1.0 (pre-release)

View file

@ -17,6 +17,14 @@ The Towerops agent enables customers to deploy SNMP polling infrastructure on th
## Quick Start
### Using Pre-built Image
Pull the latest image from GitLab Container Registry:
```bash
docker pull registry.gitlab.com/graham/towerops-agent:latest
```
### Using Docker Compose
1. Create a `docker-compose.yml` file:
@ -25,7 +33,7 @@ The Towerops agent enables customers to deploy SNMP polling infrastructure on th
version: '3.8'
services:
towerops-agent:
image: towerops/agent:latest
image: registry.gitlab.com/graham/towerops-agent:latest
restart: unless-stopped
environment:
- TOWEROPS_API_URL=https://app.towerops.com

View file

@ -0,0 +1,41 @@
version: '3.8'
services:
towerops-agent:
image: registry.gitlab.com/graham/towerops-agent:latest
container_name: towerops-agent
restart: unless-stopped
environment:
# Required: Your Towerops API URL
- TOWEROPS_API_URL=https://app.towerops.com
# Required: Agent authentication token (from Towerops web UI)
# Get this from: Organization > Agents > Create New Agent
- TOWEROPS_AGENT_TOKEN=your-agent-token-here
# Optional: How often to refresh configuration (seconds)
# Default: 300 (5 minutes)
# - CONFIG_REFRESH_SECONDS=300
# Optional: Database path for metrics buffering
# Default: /data/towerops-agent.db
# - DATABASE_PATH=/data/towerops-agent.db
# Optional: Log level (error, warn, info, debug, trace)
# Default: info
# - RUST_LOG=info
volumes:
# Persistent storage for metrics buffering
- ./data:/data
# Optional: Resource limits
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.1'
memory: 128M