A service for executing protobuf/gRPC code generation plugins running as Docker containers.
Module: github.com/easyp-tech/service
Managing protobuf/gRPC code generation across development teams becomes increasingly complex as organizations scale:
Version Inconsistencies
- Developers use different plugin versions locally, causing build failures and inconsistent generated code
- "Works on my machine" syndrome when generated code differs between environments
- Manual coordination required to keep entire teams synchronized on plugin versions
Operational Overhead
- DevOps teams spend significant time managing plugin installations across developer machines
- Each new team member requires manual setup of correct plugin versions
- Plugin updates require coordinating with every developer individually
- No centralized control over which plugin versions are approved for use
Security & Compliance Risks
- Developers install plugins from various sources without security validation
- No audit trail of which plugins were used for which builds
- Difficult to enforce security policies on code generation tools
EasyP API Service eliminates these operational headaches by centralizing plugin management:
🎯 Instant Version Control
- Deploy new plugin versions to entire team instantly via stable tags (e.g.,
grpc/go:stable) - Operations team controls plugin rollouts without touching developer machines
- Zero developer coordination required for plugin updates
🔒 Security & Consistency
- All plugins run in isolated Docker containers with security constraints
- Centralized approval process for new plugins
- Consistent execution environment regardless of developer's local setup
⚡ Developer Experience
- No local plugin installation or maintenance required
- Works identically across all environments (local, CI/CD, production)
- New team members productive immediately without plugin setup
EasyP API Service provides centralized management and execution of protobuf/gRPC plugins as isolated Docker containers. The service accepts google.protobuf.compiler.CodeGeneratorRequest via gRPC API and returns generated code by executing plugins in a secure, isolated environment.
- 🐳 Plugin isolation in Docker containers
- 📦 Self-hosted registry for plugin Docker images
- 🔄 Plugin versioning with "latest" support
- 📊 Monitoring with Prometheus and Grafana
- 🗄️ Persistence with PostgreSQL
- 🌐 gRPC + HTTP API
- 📈 Health checks and metrics
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ gRPC Client │───▶│ API Service │───▶│ Docker Registry │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ PostgreSQL │
└─────────────────┘
The service runs plugins as Docker containers, passing protobuf data through stdin/stdout.
.
├── api/ # API contracts (protobuf)
│ ├── generator/v1/ # Main code generation API
│ │ ├── generator.proto
│ │ ├── generator.pb.go
│ │ └── generator_grpc.pb.go
│ └── web/v1/ # Web API for management
│ ├── web.proto
│ ├── web.pb.go
│ ├── web.pb.gw.go
│ └── web_grpc.pb.go
├── cmd/
│ └── main.go # Server entry point
├── internal/ # Internal logic
│ ├── adapters/ # External system adapters
│ │ ├── metrics/ # Prometheus metrics collection
│ │ └── registry/ # DB and Docker operations
│ ├── api/ # Transport layer (gRPC)
│ ├── core/ # Business logic
│ └── flags/ # CLI flag processing
├── migrate/ # SQL migrations
│ └── 1.init.sql
├── registry/ # Plugin Dockerfiles examples
│ ├── protobuf/go/v1.36.10/
│ ├── grpc/go/v1.5.1/
│ ├── grpc-ecosystem/gateway/v2.27.3/
│ ├── grpc-ecosystem/openapiv2/v2.27.3/
│ └── community/pseudomuto-doc/v1.5.1/
├── docker/
│ └── Dockerfile # Service Dockerfile
├── infrastructure/ # Monitoring configurations
│ ├── grafana/
│ ├── loki/
│ ├── prometheus/
│ └── promtail/
├── config.yml # Service configuration
├── docker-compose.yml # Development infrastructure
├── easyp.yaml # easyp configuration
├── Taskfile.yml # Task automation
└── push.sh # Plugin build and push script
- Docker and docker-compose
- Task (optional)
- Go 1.24+ (for development)
# Start all services
task up
# Build and push plugins to local registry
task local-push-registry
# Full run with logs
task runOr without Task:
# Start infrastructure
docker compose up -d
# Build plugins
./push.sh localhost:5005 --push
# View service logs
docker compose logs -f service# Health check
curl http://localhost:8082/health
# Metrics
curl http://localhost:8081/metrics
# Grafana (admin/admin)
open http://localhost:3000Endpoint: localhost:8080 (gRPC)
service ServiceAPI {
rpc GenerateCode(GenerateCodeRequest) returns (GenerateCodeResponse);
}
message GenerateCodeRequest {
google.protobuf.compiler.CodeGeneratorRequest code_generator_request = 1;
string plugin_name = 2; // Format: "group/name:version"
}
message GenerateCodeResponse {
google.protobuf.compiler.CodeGeneratorResponse code_generator_response = 1;
}Endpoint: localhost:8080 (gRPC) + HTTP Gateway
service ServiceAPI {
rpc Plugins(PluginsRequest) returns (PluginsResponse) {
option (google.api.http) = { get: "/v1/plugins" };
};
}Plugins are identified in the format: {group}/{name}:{version}
protobuf/go:v1.36.10- Go protobuf plugingrpc/go:v1.5.1- Go gRPC plugingrpc-ecosystem/gateway:v2.27.3- gRPC Gatewaycommunity/pseudomuto-doc:v1.5.1- Documentation pluginprotobuf/go:latest- Latest version of Go plugin
protobuf- Core protobuf pluginsgrpc- gRPC pluginsgrpc-ecosystem- gRPC ecosystem pluginscommunity- Community plugins
# Server
SERVER_HOST=0.0.0.0
SERVER_PORT_GRPC=8080
SERVER_PORT_METRIC=8081
SERVER_PORT_HEALTH=8082
# Database
DB_POSTGRES_DSN="postgres://user:pass@localhost/db"
DB_MIGRATE_DIR="migrate"
# Docker Registry
REGISTRY_DOMAIN="localhost:5005"server:
host: "0.0.0.0"
port:
grpc: 8080
metric: 8081
health: 8082
db:
migrate_dir: "migrate"
driver: "postgres"
postgres: "postgres://easyp_svc:easyp_pass@postgres:5432/easyp_db?sslmode=disable"
registry:
domain: "localhost:5005"We welcome contributions of new plugins! Here's how to add your plugin to the registry:
# Fork the repository
git fork https://github.com/easyp-tech/easyp-api-service
# Clone your fork
git clone https://github.com/YOUR_USERNAME/easyp-api-service
cd easyp-api-service
# Create plugin directory structure
mkdir -p registry/{group}/{plugin-name}/{version}
cd registry/{group}/{plugin-name}/{version}Your plugin must be packaged as a Docker image that:
- Reads protobuf
CodeGeneratorRequestfrom stdin - Writes protobuf
CodeGeneratorResponseto stdout - Runs as a non-root user for security
- Is optimized for size (use multi-stage builds)
FROM --platform=$BUILDPLATFORM golang:1.25-alpine3.22 AS build
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
# Install upx for binary compression (optional but recommended)
RUN apk add upx=5.0.2-r0 --no-cache
# Install your protoc plugin
RUN --mount=type=cache,target=/go/pkg/mod \
go install -ldflags "-s -w" -trimpath example.com/[email protected] \
&& mv /go/bin/${GOOS}_${GOARCH}/protoc-gen-yourplugin /go/bin/protoc-gen-yourplugin || true \
&& upx --best --lzma /go/bin/protoc-gen-yourplugin
FROM scratch
# Copy essential files for non-root user
COPY --from=build --link /etc/passwd /etc/passwd
COPY --from=build --link --chown=root:root /go/bin/protoc-gen-yourplugin /protoc-gen-yourplugin
# Run as non-root user
USER nobody
ENTRYPOINT ["/protoc-gen-yourplugin"]FROM python:3.11-alpine AS build
# Install your plugin
RUN pip install --no-cache-dir yourplugin==1.0.0
FROM python:3.11-alpine
# Copy installed packages
COPY --from=build /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=build /usr/local/bin/protoc-gen-yourplugin /usr/local/bin/
# Create non-root user
RUN adduser -D -s /bin/sh plugin
USER plugin
ENTRYPOINT ["/usr/local/bin/protoc-gen-yourplugin"]FROM node:18-alpine AS build
WORKDIR /app
RUN npm install -g [email protected]
FROM node:18-alpine
# Copy global node modules
COPY --from=build /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=build /usr/local/bin /usr/local/bin
# Create non-root user
RUN adduser -D -s /bin/sh plugin
USER plugin
ENTRYPOINT ["protoc-gen-yourplugin"]# Build the plugin image
docker build -t localhost:5005/{group}/{plugin-name}:{version} .
# Test with sample protobuf request
echo "your_protobuf_request_binary_data" | \
docker run --rm -i localhost:5005/{group}/{plugin-name}:{version}Create a migration file or add to the existing migration:
-- Add your plugin to the database
INSERT INTO plugins (group_name, name, version, created_at)
VALUES ('{group}', '{plugin-name}', '{version}', now());Add your plugin to this README:
### Available Plugins
- `{group}/{plugin-name}:{version}` - Description of your plugin# Commit your changes
git add registry/{group}/{plugin-name}/
git commit -m "Add {group}/{plugin-name}:{version} plugin"
# Push to your fork
git push origin main
# Create pull request
# Include description of what your plugin does and how to use itSecurity:
- ✅ Must run as non-root user
- ✅ No network access required (use
--network=none) - ✅ Limited memory (128MB max)
- ✅ Limited CPU (1 core max)
- ✅ Stateless execution
Performance:
- ✅ Fast startup (< 5 seconds)
- ✅ Small image size (< 100MB preferred)
- ✅ Efficient memory usage
Compatibility:
- ✅ Supports standard protoc plugin protocol
- ✅ Reads from stdin, writes to stdout
- ✅ Returns proper exit codes
- ✅ Works with linux/amd64 architecture
protobuf - Core Protocol Buffers plugins
- Official protoc plugins (protoc-gen-go, protoc-gen-cpp, etc.)
- Language-specific protobuf generators
grpc - gRPC framework plugins
- Official gRPC plugins (protoc-gen-go-grpc, etc.)
- gRPC service generators
grpc-ecosystem - gRPC ecosystem tools
- grpc-gateway, grpc-web, openapi generators
- Authentication, validation tools
community - Community-maintained plugins
- Documentation generators
- Custom validation tools
- Framework-specific generators
We provide testing tools to validate your plugin:
# Test plugin compatibility
./scripts/test-plugin.sh {group}/{plugin-name}:{version}
# Validate plugin security
./scripts/security-scan.sh {group}/{plugin-name}:{version}
# Performance benchmarks
./scripts/benchmark-plugin.sh {group}/{plugin-name}:{version}For local development without PR:
# Create plugin structure
mkdir -p registry/{group}/{name}/{version}
# Create Dockerfile
# ... (see examples above)
# Add to database
docker exec -it easyp-postgres psql -U easyp_svc -d easyp_db \
-c "INSERT INTO plugins (group_name, name, version) VALUES ('{group}', '{name}', '{version}');"
# Build and push
./push.sh localhost:5005 --push# Generate from proto files
easyp generate# Local build
go build -o bin/server ./cmd/main.go
# Docker build
docker build -f docker/Dockerfile -t easyp-api-service .
# Run
./bin/server -cfg config.yml -log_level debug| Service | URL | Description |
|---|---|---|
| Grafana | http://localhost:3000 | Dashboards (admin/admin) |
| Prometheus | http://localhost:9090 | Metrics |
| Health | http://localhost:8082 | Health checks |
| Metrics | http://localhost:8081 | Prometheus metrics |
grpc_server_handled_total- gRPC request countplugin_generation_total- Plugin generation count by pluginplugin_generation_duration_seconds- Plugin execution timepostgres_queries_total- Database query count
import (
"github.com/easyp-tech/service/api/generator/v1"
"google.golang.org/grpc"
)
// Connect
conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
client := generator.NewServiceAPIClient(conn)
// Generate code
response, err := client.GenerateCode(ctx, &generator.GenerateCodeRequest{
CodeGeneratorRequest: codeGenRequest,
PluginName: "protobuf/go:v1.36.10",
})# easyp.yaml
generate:
plugins:
- remote: "localhost:8080/protobuf/go:latest"
out: .
opts:
paths: source_relative
- remote: "localhost:8080/grpc/go:v1.5.1"
out: .
opts:
paths: source_relative# Start infrastructure
task up
# Stop with cleanup
task down
# Full development cycle
task run
# Build plugins
task local-push-registry
# Manual plugin build
./push.sh localhost:5005 --push
# View images
docker images | grep localhost:5005# Check Docker network
docker network ls
# Check running containers
docker ps
# Service logs
docker compose logs service
# Restart with rebuild
task down && task up# Check available plugins in registry
curl -s http://localhost:5005/v2/_catalog
# Check plugin versions
curl -s http://localhost:5005/v2/protobuf/go/tags/list
# Manual plugin execution
docker run --rm -i localhost:5005/protobuf/go:v1.36.10 < request.bin# Connect to PostgreSQL
docker exec -it easyp-postgres psql -U easyp_svc -d easyp_db
# Check plugins in database
SELECT * FROM plugins;
# Check schema
\d plugins- Implementation of Web API for plugin management
- Web interface for plugin management
- Result caching
- Automatic plugin updates
- Audit logging
- Integration tests
- CI/CD pipeline setup
- Kubernetes manifests
- Helm charts
protobuf/go:v1.36.10- Go Protocol Buffers compilergrpc/go:v1.5.1- Go gRPC compiler
grpc-ecosystem/gateway:v2.27.3- gRPC-Gateway HTTP transcodinggrpc-ecosystem/openapiv2:v2.27.3- OpenAPI v2 documentation generator
community/pseudomuto-doc:v1.5.1- Protocol documentation generator
This project is developed by the EasyP Tech team.
For questions and suggestions, please create Issues in the repository.