Deploy a Git Application

This guide covers deploying applications directly from Git repositories on Teenode. Git Deploy enables automatic builds and deployments with support for custom build commands, environment variables, and deployment strategies.

What is Git Deploy?

Git Deploy is Teenode’s automated deployment system that:

  • Monitors your Git repository for changes
  • Automatically builds your application using custom build scripts
  • Deploys in a confidential AMD SEV-SNP container
  • Supports multiple programming languages and frameworks
  • Provides automatic SSL/TLS certificates
  • Enables rollback to previous deployments

Prerequisites

  • Teenode CLI installed and authenticated
  • Application code in a Git repository (GitHub, GitLab, Bitbucket)
  • Dockerfile or build configuration in your repository
  • Application listens on port defined by PORT environment variable

Repository Structure

Your repository should have either a Dockerfile or build configuration:

my-app/
├── Dockerfile          # Container configuration
├── .teenoderc.json     # Optional: Teenode configuration
├── package.json        # For Node.js apps
├── requirements.txt    # For Python apps
├── src/                # Application source code
├── .env.example        # Example environment variables
└── README.md

Step 1: Prepare Your Repository

Create a Dockerfile in your repository root:

# Build stage
FROM node:18-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

# Runtime stage
FROM node:18-alpine

WORKDIR /app
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

# Must listen on PORT environment variable
ENV PORT=3000
EXPOSE ${PORT}

CMD ["node", "dist/index.js"]

Or for Python applications:

FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY . .

# Set port
ENV PORT=8000
EXPOSE ${PORT}

# Run application
CMD ["python", "-m", "gunicorn", "-w", "4", "-b", "0.0.0.0:${PORT}", "app:app"]

Step 2: Configure Build Settings

Create optional .teenoderc.json for advanced build configuration:

{
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".",
    "args": {
      "NODE_ENV": "production"
    },
    "target": "runtime"
  },
  "deploy": {
    "port": 3000,
    "healthCheck": {
      "path": "/health",
      "interval": 30,
      "timeout": 5,
      "retries": 3
    },
    "resources": {
      "memory": "512Mi",
      "cpu": "500m"
    }
  },
  "autoDeploy": {
    "enabled": true,
    "branches": ["main", "production"],
    "ignorePaths": ["*.md", "docs/"]
  }
}

Step 3: Create the Project

Create a new Git Deploy project:

teenode project create \
  --name my-web-app \
  --type GIT_DEPLOY \
  --git-url https://github.com/yourusername/my-app \
  --branch main \
  --region us-east
For private repositories, you’ll need to add a deploy key. See the Private Repositories section below.

Step 4: Set Environment Variables

Configure environment variables for your application:

teenode env set my-web-app \
  DATABASE_URL="postgres://user:[email protected]/mydb" \
  API_KEY="sk-12345..." \
  LOG_LEVEL="info" \
  NODE_ENV="production"

View environment variables:

teenode env list my-web-app

Update a specific variable:

teenode env set my-web-app --update API_KEY="sk-new-key"
Environment variables are encrypted at rest. Never commit secrets to your Git repository.

Step 5: Configure Deployment Strategy

Auto-Deploy on Git Push

# Enable auto-deploy for main branch
teenode project update my-web-app \
  --auto-deploy-branch main \
  --auto-deploy-enabled true

# Deploy on any branch
teenode project update my-web-app \
  --auto-deploy-enabled true

# Disable auto-deploy
teenode project update my-web-app \
  --auto-deploy-enabled false

Manual Deployment

# Deploy from specific branch
teenode deployment create my-web-app \
  --branch feature/new-feature

# Deploy from specific commit
teenode deployment create my-web-app \
  --commit abc123def456

Step 6: Monitor Deployment

Check deployment progress:

# View deployment status
teenode deployment list my-web-app

# Watch build logs
teenode deployment logs <deployment-id> --follow

# View runtime logs
teenode project logs my-web-app --follow

# Check application metrics
teenode project metrics my-web-app

Deployment Stages

Build Stage

Your Docker image is built on Teenode infrastructure:

# View build logs
teenode deployment logs <deployment-id> --stage build

# Build takes 5-10 minutes depending on dependencies
# Progress is shown in real-time

Deployment Stage

The built image is deployed to a confidential container:

# Container starts and health checks begin
# Traffic is routed once health checks pass
# Old containers are terminated

# View deployment events
teenode deployment describe <deployment-id>

Best Practices

Multi-Stage Docker Builds

Reduce image size using multi-stage builds:

# Stage 1: Builder
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Runtime (smaller image)
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

ENV PORT=3000
CMD ["node", "dist/index.js"]

Health Checks

Include health checks in your application for reliable deployments:

// Express.js example
app.get('/health', (req, res) => {
  const health = {
    status: 'UP',
    timestamp: new Date().toISOString(),
    uptime: process.uptime()
  };
  res.json(health);
});

app.listen(process.env.PORT || 3000, '0.0.0.0', () => {
  console.log('Server running on port', process.env.PORT || 3000);
});
# Dockerfile with health check
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -f http://localhost:${PORT}/health || exit 1

Optimize Build Time

Use .dockerignore to exclude unnecessary files:

.git
.gitignore
node_modules
npm-debug.log
.env
.env.local
README.md
.DS_Store
coverage
dist
.vscode
.idea

Advanced Configuration

Build Arguments

Pass build-time variables to Docker:

teenode project update my-web-app \
  --build-arg NODE_ENV=production \
  --build-arg API_VERSION=v1
ARG NODE_ENV=development
ARG API_VERSION=v1

ENV NODE_ENV=${NODE_ENV}
ENV API_VERSION=${API_VERSION}

RUN echo "Building with NODE_ENV=${NODE_ENV} and API_VERSION=${API_VERSION}"

Custom Build Commands

Run custom commands during build:

teenode project update my-web-app \
  --pre-build-hook "npm audit" \
  --post-build-hook "npm run generate-docs"

Private Repositories

Using Deploy Keys

For private repositories, set up a deploy key:

# Generate an SSH key for Teenode
ssh-keygen -t ed25519 -f ~/.ssh/teenode_deploy_key -N ""

# Add the public key to your Git provider
cat ~/.ssh/teenode_deploy_key.pub

# Configure Teenode to use the deploy key
teenode project update my-web-app \
  --deploy-key ~/.ssh/teenode_deploy_key

# For GitHub:
# 1. Go to repository Settings > Deploy keys
# 2. Add the public key with write access enabled

Using Personal Access Tokens

Alternatively, use a personal access token:

# Update Git URL with token (for private repos)
teenode project update my-web-app \
  --git-url https://username:[email protected]/yourusername/my-app
Never commit tokens to your repository. Use deploy keys or environment variables in your CI/CD system.

Rollback and Version Management

View Deployment History

# List all deployments with versions
teenode deployment list my-web-app --limit 20

# View specific deployment details
teenode deployment describe <deployment-id>

Rollback to Previous Version

# Rollback to previous deployment
teenode deployment rollback my-web-app --target previous

# Rollback to specific deployment
teenode deployment rollback my-web-app --id <deployment-id>

# Rollback from specific commit
teenode deployment rollback my-web-app --commit abc123

Troubleshooting

Build Fails

Check the build logs for errors:

# View full build output
teenode deployment logs <deployment-id> --stage build --raw

# Common issues:
# - Missing dependencies in package.json
# - Incorrect Dockerfile syntax
# - Insufficient memory during build
# - Network issues downloading dependencies

Application Doesn’t Start

# Check runtime logs
teenode project logs my-web-app --follow

# Ensure application listens on PORT environment variable
# Most frameworks default to 3000 if not specified

Health Checks Failing

If health checks are failing, the deployment will not complete:

# Test health endpoint locally
curl -f http://localhost:3000/health

# Check health check configuration in .teenoderc.json
# Increase timeout if needed for slow startup

Git Authentication Errors

# Verify deploy key is added to repository
# Check that the key format is correct (ed25519 recommended)
# Ensure public key is in repository settings

# Test Git access manually
ssh -i ~/.ssh/teenode_deploy_key [email protected]

Cost Optimization

Reduce Build Artifacts

# Only include necessary files in final image
FROM node:18-alpine
WORKDIR /app

# Copy only necessary files
COPY package.json package-lock.json ./
RUN npm ci --only=production

COPY dist/ ./dist
COPY config/ ./config

# Reduces image size from 500MB to 100MB

Resource Limits

# Configure resource limits
teenode project update my-web-app \
  --memory 512Mi \
  --cpu 500m

# Reduces costs for light workloads

Integrations

Slack Notifications

# Enable deployment notifications
teenode project update my-web-app \
  --notify-slack true \
  --slack-webhook https://hooks.slack.com/services/YOUR/WEBHOOK/URL

GitHub Actions

Trigger Teenode deployments from GitHub Actions:

# .github/workflows/deploy.yml
name: Deploy to Teenode

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Deploy to Teenode
        run: |
          npm install -g teenode-cli
          teenode auth login --token ${{ secrets.TEENODE_TOKEN }}
          teenode deployment create my-web-app --branch main

Next Steps

Your application is now running in a confidential AMD SEV-SNP container with automatic deployments enabled!