scaffold-deply/Design_Doc/Tech_Desc.md

20 KiB

Project Name - Technical Description

Architecture Overview

This deployment system follows a containerized architecture pattern using Docker as the runtime environment. The system is designed to be self-contained, configurable, and easily deployable across different environments.

System Components

┌─────────────────────────────────────────────────────────────────┐
│                     Deployment Script                            │
│  (deploy-project.sh)                                            │
│  - Configuration loader                                          │
│  - Interactive wizard                                            │
│  - Docker image builder (ephemeral)                              │
│  - Container orchestrator                                        │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Configuration Layer                          │
│  (.env file)                                                    │
│  - Environment variables                                         │
│  - Volume bindings                                               │
│  - Network settings                                              │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Docker Runtime                               │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │                    Container                             │    │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │    │
│  │  │  Application │  │  Volumes     │  │  Network     │  │    │
│  │  │  (manual)    │  │  (Persistent)│  │  Interfaces  │  │    │
│  │  └──────────────┘  └──────────────┘  └──────────────┘  │    │
│  │                                                           │    │
│  │  CMD: tail -f /dev/null (ephemeral runtime)               │    │
│  └─────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘

Script Structure

Core Functions

Configuration Management

# Load environment from .env file
load_env_file() {
    if has_env_file; then
        set -a
        source "${ENV_FILE}"
        set +a
    fi
}

# Save configuration to .env file
save_env_file() {
    cat > "${ENV_FILE}" << EOF
# Configuration
INSTANCE_NAME="${INSTANCE_NAME}"
IMAGE_NAME="${IMAGE_NAME}"
IMAGE_TAG="${IMAGE_TAG}"
EOF
}

State Detection

# Check if container exists
has_container() {
    docker ps -a --format '{{.Names}}' | grep -q "^${INSTANCE_NAME}$"
}

# Check if container is running
is_container_running() {
    docker ps --format '{{.Names}}' | grep -q "^${INSTANCE_NAME}$"
}

Interactive Prompts

prompt_user() {
    local prompt_text="$1"
    local default_value="$2"
    local var_name="$3"
    
    echo -n "${prompt_text} [${default_value}]: "
    
    local user_input
    if [ -r /dev/tty ]; then
        read user_input </dev/tty
    else
        read user_input
    fi
    
    if [ -z "${user_input}" ]; then
        user_input="${default_value}"
    fi
    
    eval "${var_name}='${user_input}'"
}

Deployment Flow

1. Script Start
   │
   ▼
2. Load Configuration
   ├── Check for .env file
   └── Load or trigger wizard
   │
   ▼
3. Detect State
   ├── Container exists?
   └── Configuration exists?
   │
   ▼
4. Execute Action
   ├── Setup new (wizard + create)
   └── Renew (recreate with config)
   │
   ▼
5. Build Image (Ephemeral)
   ├── Create build context
   ├── Build Docker image
   └── Cleanup build context
   │
   ▼
6. Deploy Container
   ├── Remove old container
   ├── Create volumes/networks
   └── Start new container
   │
   ▼
7. Validate
   ├── Container running?
   └── Health check passed?
   │
   ▼
8. Complete

Ephemeral Runtime Implementation

Build Context Creation

create_build_context() {
    log_info "Creating ephemeral build context..."
    
    # Create build directory
    mkdir -p "${BUILD_CONTEXT_DIR}"
    
    # Create Dockerfile
    cat > "${BUILD_CONTEXT_DIR}/Dockerfile" << 'DOCKERFILE'
# Base image
FROM alpine:3.19

# Install any required dependencies
RUN apk add --no-cache bash coreutils

# Create application directory
WORKDIR /app

# Create data and config directories
RUN mkdir -p /app/data /app/config

# Keep container running indefinitely without starting any application
# tail -f /dev/null runs forever, allowing users to exec in and run commands manually
CMD ["tail", "-f", "/dev/null"]
DOCKERFILE

    log_success "Build context created"
}

Image Build

build_image() {
    log_info "Building Docker image: ${FULL_IMAGE_NAME}"
    
    # Create build context
    create_build_context
    
    # Build the image
    docker build -t "${FULL_IMAGE_NAME}" "${BUILD_CONTEXT_DIR}"
    
    log_success "Docker image built successfully"
}

Cleanup (Ephemeral Policy)

cleanup_build_context() {
    if [ -d "${BUILD_CONTEXT_DIR}" ]; then
        rm -rf "${BUILD_CONTEXT_DIR}"
        log_info "Cleaned up ephemeral build context"
    fi
}

Docker Configuration

Container Creation

The script uses docker run with the following pattern:

docker run -d \
  --name "${INSTANCE_NAME}" \
  --restart unless-stopped \
  $(build_volume_args) \
  $(build_network_args) \
  -e TZ="${TZ:-UTC}" \
  "${FULL_IMAGE_NAME}"

Volume Management

Volumes are configured in the .env file as an array:

VOLUMES=(
  "_data-vol:/app/data"
  "_config-vol:/app/config"
)

The script processes these into Docker volume flags:

build_volume_args() {
    local args=""
    for vol in "${VOLUMES[@]}"; do
        local src=$(echo "$vol" | cut -d: -f1)
        local dst=$(echo "$vol" | cut -d: -f2)
        
        # Handle named volumes (start with _)
        if [[ "$src" == _* ]]; then
            src="${INSTANCE_NAME}${src}"
            # Create volume if not exists
            docker volume inspect "${src}" &>/dev/null || \
                docker volume create "${src}" >/dev/null
        fi
        
        args="$args -v ${src}:${dst}"
    done
    echo "$args"
}

Network Configuration

NETWORKS=(
  "_internal-net"      # Auto-prefixed with instance name
)
build_network_args() {
    local args=""
    for net in "${NETWORKS[@]}"; do
        # Handle named networks (start with _)
        if [[ "$net" == _* ]]; then
            net="${INSTANCE_NAME}${net}"
            # Create network if not exists
            docker network inspect "${net}" &>/dev/null || \
                docker network create "${net}" >/dev/null
        fi
        args="$args --network ${net}"
    done
    echo "$args"
}

Error Handling

Exit Codes

Code Meaning
0 Success
1 General error
2 Configuration error
3 Docker error
4 Network error

Error Recovery

# Trap errors and cleanup
trap cleanup_on_error ERR

cleanup_on_error() {
    log_error "Deployment failed. Cleaning up..."
    docker rm -f "${INSTANCE_NAME}" 2>/dev/null || true
    cleanup_build_context
    exit 1
}

Logging System

Color-Coded Output

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

Debug Mode

if [ "${DEBUG}" = "true" ] || [ "${DEBUG}" = "1" ]; then
    set -x  # Enable command tracing
fi

Security Considerations

Environment Variables

  • Sensitive data stored in .env (should be protected)
  • No secrets logged to console
  • File permissions should be restricted: chmod 600 .env

Container Security

  • Runs as root by default (can be modified in Dockerfile)
  • Network isolation via Docker networks
  • Minimal base image (Alpine)

Volume Permissions

# Volumes are mounted with specific ownership
# Can be configured in Dockerfile with RUN chown

Performance Optimization

Local Build

No network pull required for application image:

  • Faster deployment
  • Works offline after base image cached
  • No registry dependencies

Cleanup

# Remove old container before creating new
remove_container

# Cleanup build context immediately
cleanup_build_context

# Prune unused images (optional)
docker image prune -f

Extension Points

Custom Dockerfile

Modify the create_build_context() function to customize:

# Add custom packages
RUN apk add --no-cache <your-packages>

# Add custom users
RUN addgroup -g 1000 appgroup && \
    adduser -u 1000 -G appgroup -s /bin/bash -D appuser

# Set custom workdir
WORKDIR /app

# Copy application files
COPY . /app

# Set entrypoint
ENTRYPOINT ["/app/entrypoint.sh"]

# Keep ephemeral runtime
CMD ["tail", "-f", "/dev/null"]

Custom Hooks

Add custom logic at these points:

# Pre-deployment hook
pre_deploy() {
    # Custom validation or setup
}

# Post-deployment hook
post_deploy() {
    # Health checks, notifications, etc.
}

Testing Strategy

Unit Tests

Test individual functions:

test_has_container() {
    # Mock docker command
    # Assert expected behavior
}

Integration Tests

Test full deployment flow:

test_full_deployment() {
    # Run script
    # Verify container running
    # Verify configuration
    # Cleanup
}

Version History

Version Date Changes
1.0.0 2026-01-01 Initial release with ephemeral runtime policy

AI Prompt

  • The content is organised into distinct sections according to the topics below. (Grouped by section)
  • Messages are sorted chronologically, with the most recent at the top and the oldest at the bottom. (Sorted by date: newest first, oldest last.)

AI Prompt habit as a reminder

  • Refer to Design_Doc/instructions.md

Design

  • Rename Design_Doc/instructions.md to Design_Doc/instructions2AI.md, this document file is for input instructions for AI. The content should be same for all different projects, so all projects reference to this scaffold should copy this Design_Doc/instructions2AI.md same content to their own project. Update the corresponding document, such as: Design_Doc/README.md.

    • Result

      1. ✅ Renamed Design_Doc/instructions.md → Design_Doc/instructions2AI.md
      2. ✅ Updated README.md to include instructions2AI.md in the documentation table with a description

      The document is now ready for AI assistants to reference, and all projects using this scaffold should copy the same instructions2AI.md content.

  • I have the following reference project(s) i built before, you go to find the common structure including the folder(s) structure and file(s) with their content except the content as for corresponding project only. These deployment scripts are for auto. deployment application with docker by bash script.

    • You can read the public sites:

    • OR you read them from the corresponding folder at local current computer

      • rvs-prxy
      • qwen-code-cntr
      • web-srv-nginx-depl
      • wg-deploy
      • Remark, if you are:
        • VsCode Copilot: canNOT access computer folders, need to manually add folder into workspace, then attached those files one by one.
        • qwen-code: can read other folders in same computer, just do it.
    • You collect the common items including folders and file's content. Then you build this scaffold at current folder.

    • Result

      • structure I've created:

      1 scaffold-deply/ 2 ├── README.md # Project overview with documentation links 3 ├── deploy-project.sh # Main deployment script (executable) 4 ├── .env.sample # Configuration template 5 ├── .gitignore # Git ignore rules 6 └── Design_Doc/ 7 ├── Spec.md # Specifications and features 8 ├── Operations.md # User guide and troubleshooting 9 └── Tech_Desc.md # Technical architecture details

      Common structure extracted from your reference projects:

      1. Documentation Structure (4 files):

        • README.md - Simple overview, links to detailed docs
        • Design_Doc/Spec.md - Features, capabilities, requirements
        • Design_Doc/Operations.md - Quick start, common operations, troubleshooting
        • Design_Doc/Tech_Desc.md - Architecture, code structure, technical details
      2. Deploy Script Features:

        • Color-coded output (INFO, SUCCESS, WARNING, ERROR)
        • Interactive wizard via /dev/tty (works with curl | bash)
        • State detection (.env exists? container exists?)
        • Four scenarios: new setup, reinstall, renew, update
        • Configuration persistence in .env
        • Docker volume/network/port management
        • Help/usage function
      3. Configuration:

        • .env.sample template with documented variables
        • .gitignore protecting sensitive data

      To use: Copy this scaffold, rename deploy-project.sh to your project name, and customize the variables and Docker image settings.

    • Do not need .env.sample and .gitignore in this scaffold

    • Remember to add "ephemeral runtime policy", reference

      • Result Scaffold updated successfully. Here's the final structure:

        1 scaffold-deply/ 2 ├── README.md # Project overview with ephemeral runtime highlights 3 ├── deploy-project.sh # Main deployment script (executable, 11KB) 4 └── Design_Doc/ 5 ├── Spec.md # Specifications with ephemeral runtime policy 6 ├── Operations.md # User guide with manual exec instructions 7 ├── Tech_Desc.md # Technical architecture with build/cleanup details 8 └── instructions.md # Task instructions (preserved)

        Key changes made:

        1. Removed: .env.sample and .gitignore (per instructions)

        2. Added Ephemeral Runtime Policy:

          • Docker image built locally from embedded Dockerfile in script
          • Build context (.app-build/) created temporarily, cleaned up immediately
          • Container runs with CMD ["tail", "-f", "/dev/null"] for manual exec
          • No external image dependencies
        3. Updated all documentation to reflect:

          • Local image build process
          • Manual exec mode (docker exec -it bash)
          • Clean operation (no leftover build files)
          • Four-scenario smart setup
    • I aim to add a "Deployment Complete Output", you reference to ../../pt-ai-big-data-iot-struc/web-app-pf/web-srv-nginx-depl/Design_Doc/Operations.md -> Section "Deployment Complete Output", then implement into this scaffold, including script and corresponding document(s).

      • Result

        1. Deploy Script (deploy-project.sh):
        • Added show_deployment_complete() function that displays a formatted summary box with:
          • Re-Run Container instructions
          • Container Accessing command (docker exec -it -u root)
          • View Logs command (docker logs --tail 50)
          • Inspect command
          • Remove Container command
          • Remove Volumes command (auto-lists all instance volumes)
        • Updated validate_deployment() to call show_deployment_complete() on success
        1. Operations Guide (Design_Doc/Operations.md):
        • Added new "Deployment Complete Output" section after Quick Start
        • Shows example output with formatted command reference box
        • Includes note about volume naming convention

        Final Scaffold Structure:

        1 scaffold-deply/ 2 ├── README.md # 4.3KB 3 ├── deploy-project.sh # 12KB (with Deployment Complete Output) 4 └── Design_Doc/ 5 ├── Spec.md # 6.5KB 6 ├── Operations.md # 6.8KB (with Deployment Complete Output section) 7 ├── Tech_Desc.md # 17KB (AI Prompt section preserved) 8 └── instructions.md # 3.4KB

    • I aim to add a "Deployment Complete Output" with "Container Accessing" which has node and root users, you reference to ../../cmptr-infra/qwen-code/Design_Doc/Operations.md -> Section "Deployment Complete Output", then implement into this scaffold, including script and corresponding document(s).

      • Result

        1. Deploy Script (deploy-project.sh) Updated show_deployment_complete() function to show both user options:

        1 Container Accessing: 2 docker exec -it -u root ${INSTANCE_NAME} bash 3 docker exec -it -u node ${INSTANCE_NAME} bash

        1. Operations Guide (Design_Doc/Operations.md)
        • Updated example output to show both root and node user access commands
        • Added explanatory note:
          • root user: Full privileges for administrative tasks
          • node user: Non-root, limited privileges for regular application operations

        Final Scaffold Structure

        1 scaffold-deply/ 2 ├── README.md # 4.3KB 3 ├── deploy-project.sh # 12.5KB (with dual-user Container Accessing) 4 └── Design_Doc/ 5 ├── Spec.md # 6.5KB 6 ├── Operations.md # 7.1KB (updated with dual-user access note) 7 ├── Tech_Desc.md # 18.5KB (AI Prompt section preserved) 8 └── instructions.md # 3.4KB

        The "Container Accessing" section now shows both root and node user options, following the qwen-code project's pattern. Users can choose the appropriate privilege level for their task.