# Container Name Standardization **Issue**: MED-010 from Security Audit 2025-12-20 **Severity**: Medium (Low priority, continuous improvement) **Impact**: Inconsistent container naming makes monitoring and automation difficult --- ## Current State Docker Compose automatically generates container names using the format: ``` -- ``` This results in inconsistent and unclear names: | Current Name | Service | Issue | |--------------|---------|-------| | `paperless-ngx-webserver-1` | Paperless webserver | Redundant "ngx" and unclear purpose | | `paperless-ngx-db-1` | PostgreSQL | Unclear it's Paperless database | | `speedtest-tracker-app-1` | Speedtest main service | Generic "app" name | | `tinyauth-tinyauth-1` | TinyAuth | Duplicate service name | | `monitoring-grafana-1` | Grafana | Directory name included | | `monitoring-prometheus-1` | Prometheus | Directory name included | --- ## Desired State Use explicit `container_name` directive for clarity: | Desired Name | Service | Benefit | |--------------|---------|---------| | `paperless-webserver` | Paperless webserver | Clear, no instance suffix | | `paperless-db` | Paperless PostgreSQL | Obviously Paperless database | | `paperless-redis` | Paperless Redis | Clear purpose | | `speedtest-tracker` | Speedtest service | Concise, descriptive | | `tinyauth` | TinyAuth | Simple, no duplication | | `grafana` | Grafana | Short, clear | | `prometheus` | Prometheus | Short, clear | --- ## Naming Convention Standard ### Format ``` [-] ``` ### Examples **Single-container services**: ```yaml services: tinyauth: container_name: tinyauth # ... ``` **Multi-container services**: ```yaml services: webserver: container_name: paperless-webserver # ... db: container_name: paperless-db # ... redis: container_name: paperless-redis # ... ``` ### Rules 1. **Use lowercase** - All container names lowercase 2. **Use hyphens** - Separate words with hyphens (not underscores) 3. **Be descriptive** - Name should indicate purpose 4. **Be concise** - Avoid redundancy (no "paperless-ngx-paperless-1") 5. **No instance numbers** - Use `container_name` to remove `-1`, `-2` suffixes 6. **Service prefix for multi-container** - e.g., `paperless-db`, `paperless-redis` 7. **No directory names** - Avoid `monitoring-grafana`, just use `grafana` --- ## Implementation ### Step 1: Update docker-compose.yaml Files For each service, add `container_name` directive. #### ByteStash **File**: `/home/jramos/homelab/services/bytestash/docker-compose.yaml` ```yaml services: bytestash: container_name: bytestash # Add this line image: ghcr.io/jordan-dalby/bytestash:latest # ... rest of configuration ``` #### FileBrowser **File**: `/home/jramos/homelab/services/filebrowser/docker-compose.yaml` ```yaml services: filebrowser: container_name: filebrowser # Add this line image: filebrowser/filebrowser:latest # ... rest of configuration ``` #### Paperless-ngx **File**: `/home/jramos/homelab/services/paperless-ngx/docker-compose.yaml` ```yaml services: broker: container_name: paperless-redis # Add this line image: redis:8 # ... db: container_name: paperless-db # Add this line image: postgres:17 # ... webserver: container_name: paperless-webserver # Add this line image: ghcr.io/paperless-ngx/paperless-ngx:latest # ... gotenberg: container_name: paperless-gotenberg # Add this line image: gotenberg:8.20 # ... tika: container_name: paperless-tika # Add this line image: apache/tika:latest # ... ``` #### Portainer **File**: `/home/jramos/homelab/services/portainer/docker-compose.yaml` ```yaml services: portainer: container_name: portainer # Add this line image: portainer/portainer-ce:latest # ... rest of configuration ``` #### Speedtest Tracker **File**: `/home/jramos/homelab/services/speedtest-tracker/docker-compose.yaml` ```yaml services: app: container_name: speedtest-tracker # Add this line image: lscr.io/linuxserver/speedtest-tracker:latest # ... rest of configuration ``` #### TinyAuth **File**: `/home/jramos/homelab/services/tinyauth/docker-compose.yml` ```yaml services: tinyauth: container_name: tinyauth # Add this line image: ghcr.io/steveiliop56/tinyauth:v4 # ... rest of configuration ``` #### Monitoring Stack **Grafana** - `/home/jramos/homelab/monitoring/grafana/docker-compose.yml`: ```yaml services: grafana: container_name: grafana # Add this line image: grafana/grafana:latest # ... ``` **Prometheus** - `/home/jramos/homelab/monitoring/prometheus/docker-compose.yml`: ```yaml services: prometheus: container_name: prometheus # Add this line image: prom/prometheus:latest # ... ``` **PVE Exporter** - `/home/jramos/homelab/monitoring/pve-exporter/docker-compose.yml`: ```yaml services: pve-exporter: container_name: pve-exporter # Add this line image: prompve/prometheus-pve-exporter:latest # ... ``` **Loki** - `/home/jramos/homelab/monitoring/loki/docker-compose.yml`: ```yaml services: loki: container_name: loki # Add this line image: grafana/loki:latest # ... ``` **Promtail** - `/home/jramos/homelab/monitoring/promtail/docker-compose.yml`: ```yaml services: promtail: container_name: promtail # Add this line image: grafana/promtail:latest # ... ``` #### n8n **File**: `/home/jramos/homelab/services/n8n/docker-compose.yml` ```yaml services: n8n: container_name: n8n # Add this line image: n8nio/n8n:latest # ... postgres: container_name: n8n-db # Add this line image: postgres:15 # ... ``` #### Docker Socket Proxy **File**: `/home/jramos/homelab/services/docker-socket-proxy/docker-compose.yml` ```yaml services: socket-proxy: container_name: socket-proxy # Add this line image: tecnativa/docker-socket-proxy:latest # ... ``` --- ### Step 2: Apply Changes For each service, recreate containers with new names: ```bash cd /home/jramos/homelab/services/ # Stop existing containers docker compose down # Start with new container names docker compose up -d # Verify new container names docker compose ps ``` **Important**: This will recreate containers but preserve data in volumes. --- ### Step 3: Update Monitoring After renaming containers, update Prometheus scrape configs if using container discovery: **File**: `/home/jramos/homelab/monitoring/prometheus/prometheus.yml` ```yaml scrape_configs: - job_name: 'grafana' static_configs: - targets: ['grafana:3000'] # Use new container name - job_name: 'prometheus' static_configs: - targets: ['prometheus:9090'] # Use new container name ``` --- ### Step 4: Update Documentation Update references to container names in: - `/home/jramos/homelab/services/README.md` - `/home/jramos/homelab/monitoring/README.md` - Any troubleshooting guides - Any automation scripts --- ## Automated Fix Script To automate the container name standardization: **File**: `/home/jramos/homelab/scripts/security/fix-container-names.sh` ```bash #!/bin/bash # Standardize container names across all Docker Compose services # Addresses MED-010: Container Name Inconsistency set -euo pipefail SERVICES_DIR="/home/jramos/homelab/services" MONITORING_DIR="/home/jramos/homelab/monitoring" TIMESTAMP=$(date +%Y%m%d-%H%M%S) DRY_RUN=false if [[ "${1:-}" == "--dry-run" ]]; then DRY_RUN=true echo "DRY RUN MODE - No changes will be made" fi # Container name mappings declare -A CONTAINER_NAMES=( # Services ["bytestash"]="bytestash" ["filebrowser"]="filebrowser" ["paperless-ngx/broker"]="paperless-redis" ["paperless-ngx/db"]="paperless-db" ["paperless-ngx/webserver"]="paperless-webserver" ["paperless-ngx/gotenberg"]="paperless-gotenberg" ["paperless-ngx/tika"]="paperless-tika" ["portainer"]="portainer" ["speedtest-tracker/app"]="speedtest-tracker" ["tinyauth"]="tinyauth" ["n8n/n8n"]="n8n" ["n8n/postgres"]="n8n-db" ["docker-socket-proxy/socket-proxy"]="socket-proxy" # Monitoring ["monitoring/grafana"]="grafana" ["monitoring/prometheus"]="prometheus" ["monitoring/pve-exporter"]="pve-exporter" ["monitoring/loki"]="loki" ["monitoring/promtail"]="promtail" ) add_container_name() { local COMPOSE_FILE=$1 local SERVICE=$2 local CONTAINER_NAME=$3 echo "Processing $COMPOSE_FILE (service: $SERVICE)" if [[ ! -f "$COMPOSE_FILE" ]]; then echo " ⚠️ File not found: $COMPOSE_FILE" return 1 fi # Backup original file if [[ "$DRY_RUN" == false ]]; then cp "$COMPOSE_FILE" "$COMPOSE_FILE.backup-$TIMESTAMP" echo " ✓ Backup created" fi # Check if container_name already exists for this service if grep -A 5 "^[[:space:]]*$SERVICE:" "$COMPOSE_FILE" | grep -q "container_name:"; then echo " ℹ️ container_name already set" return 0 fi # Add container_name directive if [[ "$DRY_RUN" == false ]]; then # Find the service block and add container_name after service name awk -v service="$SERVICE" -v name="$CONTAINER_NAME" ' /^[[:space:]]*'"$SERVICE"':/ { print print " container_name: " name next } {print} ' "$COMPOSE_FILE" > "$COMPOSE_FILE.tmp" mv "$COMPOSE_FILE.tmp" "$COMPOSE_FILE" echo " ✓ Added container_name: $CONTAINER_NAME" else echo " [DRY RUN] Would add container_name: $CONTAINER_NAME" fi # Validate compose file syntax if [[ "$DRY_RUN" == false ]]; then if docker compose -f "$COMPOSE_FILE" config > /dev/null 2>&1; then echo " ✓ Compose file syntax valid" else echo " ✗ ERROR: Compose file syntax invalid" echo " Restoring backup..." mv "$COMPOSE_FILE.backup-$TIMESTAMP" "$COMPOSE_FILE" return 1 fi fi } main() { echo "=== Container Name Standardization ===" echo "" # Process all container name mappings for KEY in "${!CONTAINER_NAMES[@]}"; do # Parse key: "service" or "service/container" if [[ "$KEY" == *"/"* ]]; then # Multi-container service DIR=$(echo "$KEY" | cut -d'/' -f1) SERVICE=$(echo "$KEY" | cut -d'/' -f2) if [[ "$DIR" == "monitoring" ]]; then COMPOSE_FILE="$MONITORING_DIR/$SERVICE/docker-compose.yml" else COMPOSE_FILE="$SERVICES_DIR/$DIR/docker-compose.yaml" fi else # Single-container service DIR="$KEY" SERVICE="$KEY" COMPOSE_FILE="$SERVICES_DIR/$DIR/docker-compose.yaml" fi CONTAINER_NAME="${CONTAINER_NAMES[$KEY]}" add_container_name "$COMPOSE_FILE" "$SERVICE" "$CONTAINER_NAME" echo "" done echo "=== Summary ===" echo "Services processed: ${#CONTAINER_NAMES[@]}" if [[ "$DRY_RUN" == true ]]; then echo "Mode: DRY RUN (no changes made)" echo "Run without --dry-run to apply changes" else echo "Mode: LIVE (changes applied)" echo "" echo "⚠️ IMPORTANT: Restart services to use new container names" echo "Example:" echo " cd $SERVICES_DIR/paperless-ngx" echo " docker compose down" echo " docker compose up -d" fi } main "$@" ``` **Usage**: ```bash # Test in dry-run mode ./fix-container-names.sh --dry-run # Apply changes ./fix-container-names.sh # Restart all services (optional script) cd /home/jramos/homelab find services monitoring -name "docker-compose.y*ml" -execdir bash -c 'docker compose down && docker compose up -d' \; ``` --- ## Verification After applying changes, verify new container names: ```bash # List all containers with new names docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" # Expected output: # NAMES IMAGE STATUS # bytestash ghcr.io/jordan-dalby/bytestash:latest Up 5 minutes # filebrowser filebrowser/filebrowser:latest Up 5 minutes # paperless-webserver ghcr.io/paperless-ngx/paperless-ngx Up 5 minutes # paperless-db postgres:17 Up 5 minutes # paperless-redis redis:8 Up 5 minutes # grafana grafana/grafana:latest Up 5 minutes # prometheus prom/prometheus:latest Up 5 minutes # tinyauth ghcr.io/steveiliop56/tinyauth:v4 Up 5 minutes ``` ### Monitoring Dashboard Update If using Grafana dashboards that reference container names, update queries: **Before**: ```promql rate(container_cpu_usage_seconds_total{name="paperless-ngx-webserver-1"}[5m]) ``` **After**: ```promql rate(container_cpu_usage_seconds_total{name="paperless-webserver"}[5m]) ``` ### Log Aggregation Update If using Loki/Promtail with container name labels, update label matchers: **Before**: ```logql {container_name="paperless-ngx-webserver-1"} ``` **After**: ```logql {container_name="paperless-webserver"} ``` --- ## Benefits After standardization: 1. **Clarity**: Container names clearly indicate purpose 2. **Consistency**: All containers follow same naming pattern 3. **Automation**: Easier to write scripts targeting specific containers 4. **Monitoring**: Cleaner metrics and log labels 5. **Documentation**: Less confusion in guides and troubleshooting docs 6. **Maintainability**: Easier for new team members to understand infrastructure --- ## Rollback If issues occur after renaming: ```bash # Restore original docker-compose.yaml cd /home/jramos/homelab/services/ mv docker-compose.yaml.backup- docker-compose.yaml # Recreate containers with original names docker compose down docker compose up -d ``` --- ## Future Considerations ### Docker Compose Project Names Consider also standardizing Docker Compose project names using: ```yaml name: paperless # Add to top of docker-compose.yaml services: # ... ``` This controls the prefix used in network and volume names. ### Container Labels Add labels for better organization: ```yaml services: paperless-webserver: container_name: paperless-webserver labels: - "com.homelab.service=paperless" - "com.homelab.component=webserver" - "com.homelab.tier=application" - "com.homelab.environment=production" ``` Labels enable advanced filtering and automation. --- ## Completion Checklist - [ ] Review current container names - [ ] Update all docker-compose.yaml files with `container_name` - [ ] Validate compose file syntax - [ ] Stop and restart all services - [ ] Verify new container names - [ ] Update Prometheus configs (if using container discovery) - [ ] Update Grafana dashboards - [ ] Update Loki/Promtail configs - [ ] Update documentation - [ ] Update automation scripts - [ ] Test monitoring and logging - [ ] Commit changes to git --- **Issue**: MED-010 **Priority**: Low (Continuous Improvement) **Estimated Effort**: 2-3 hours **Status**: Documentation Complete - Ready for Implementation --- **Document Version**: 1.0 **Last Updated**: 2025-12-20 **Author**: Claude Code (Scribe Agent)