Digital Ocean App Platform
DigitalOcean App Platform is a fully managed Platform-as-a-Service (PaaS) that allows you to quickly build, deploy, and scale web applications, static sites, APIs, and background services. It integrates seamlessly with other DigitalOcean services like Managed Databases and Spaces, making it ideal for developers seeking a streamlined, opinionated deployment experience within the DO ecosystem.
You are an expert in deploying, scaling, and managing web applications on DigitalOcean App Platform, having successfully launched and maintained numerous production services. You understand its component-based architecture and how to leverage its Git-driven deployment model for efficient development workflows. ## Key Points - name: my-web-service - name: my-frontend-site - name: api-service - name: frontend-site - name: queue-processor - name: image-resizer - name: my-service - name: my-postgres-db # Must match the name of an existing Managed Database - name: api-service * **Leverage Managed Databases**: Integrate with DigitalOcean Managed Databases for reliable, scalable, and secure data storage. App Platform handles the secure injection of connection strings. * **Hardcoding Secrets in `app.yaml`**: Committing API keys, database passwords, or other sensitive information directly into your `app.yaml` or source code. * **Manual Deployments Only**: Relying solely on manual deployments through the control panel for production applications. ## Quick Example ```bash # On macOS using Homebrew brew install doctl # On Linux (example for Debian/Ubuntu) sudo snap install doctl --classic ``` ```bash doctl auth init # Follow the prompts to enter your DigitalOcean API token ```
skilldb get deployment-hosting-services-skills/Digital Ocean App PlatformFull skill: 248 linesYou are an expert in deploying, scaling, and managing web applications on DigitalOcean App Platform, having successfully launched and maintained numerous production services. You understand its component-based architecture and how to leverage its Git-driven deployment model for efficient development workflows.
Core Philosophy
DigitalOcean App Platform operates on a "build from source" philosophy, taking your code directly from a Git repository (GitHub, GitLab, or public repos) and automatically building, deploying, and scaling it. It's a fully managed PaaS designed to abstract away infrastructure complexities, allowing developers to focus purely on application logic. The platform embraces a component-based architecture where your application can consist of various interconnected parts: web services, static sites, workers, cron jobs, and serverless functions.
The platform prioritizes ease of use and rapid iteration. By defining your entire application's structure and dependencies in an app.yaml specification file, you gain Infrastructure-as-Code capabilities, ensuring consistent and repeatable deployments. It's an excellent choice when you need quick time-to-market, automatic HTTPS, global CDN, and scalable infrastructure without deep DevOps expertise, especially if you're already using other DigitalOcean services.
Setup
Setting up with DigitalOcean App Platform primarily involves authenticating with your DigitalOcean account and defining your application's components using an app.yaml specification file. The doctl CLI is your primary tool for programmatic interaction.
1. Install doctl CLI
First, ensure you have the DigitalOcean CLI (doctl) installed. Refer to the official DigitalOcean documentation for installation instructions specific to your OS.
# On macOS using Homebrew
brew install doctl
# On Linux (example for Debian/Ubuntu)
sudo snap install doctl --classic
2. Authenticate doctl
Generate a Personal Access Token from your DigitalOcean control panel (API > Tokens/Keys) and configure doctl. Ensure the token has read and write permissions for apps.
doctl auth init
# Follow the prompts to enter your DigitalOcean API token
3. Define Your Application with app.yaml
The core of an App Platform deployment is the app.yaml specification file. This file describes all components of your application. Create an app.yaml at the root of your project repository.
# app.yaml
# This example defines a Node.js web service and a static site.
services:
- name: my-web-service
github:
repo: your-github-username/your-repo-name
branch: main
deploy_on_push: true
instance_count: 1
instance_size_slug: basic-xxs # e.g., basic-xxs, professional-s
routes:
- path: /api
build_command: npm install
run_command: npm start
envs:
- key: NODE_ENV
value: production
- key: DATABASE_URL
scope: RUN_AND_BUILD_TIME # or RUN_TIME, BUILD_TIME
value: ${DB_CONNECTION_STRING} # Link to a database or secret
static_sites:
- name: my-frontend-site
github:
repo: your-github-username/your-repo-name
branch: main
deploy_on_push: true
output_dir: build # Directory containing static assets after build
build_command: npm install && npm run build
routes:
- path: /
4. Deploy Your Application
Once your app.yaml is committed to your repository, you can create or update your application using doctl.
# Create a new app based on the app.yaml in the current directory
doctl apps create --spec .do/app.yaml
# If you prefer to specify the path explicitly
# doctl apps create --spec /path/to/your/app.yaml
# To update an existing app (replace 'my-app' with your app's name or ID)
doctl apps update my-app --spec .do/app.yaml
The platform will then fetch your code, build it according to your app.yaml, and deploy it. Subsequent pushes to the specified Git branch will trigger automatic redeployments if deploy_on_push is true.
Key Techniques
1. Defining a Multi-Component Application
An app.yaml can define various components like web services, static sites, workers, and functions, all within a single application. This allows for cohesive microservice architectures or mixed-technology applications.
# .do/app.yaml
name: my-fullstack-app
region: nyc # Or another preferred region like sfo, fra, blr
services:
- name: api-service
github:
repo: your-github-username/your-api-repo
branch: main
build_command: npm install && npm run build
run_command: node dist/server.js
routes:
- path: /api
envs:
- key: PORT
value: "8080" # App Platform injects PORT, but you might need to set it for your app
- key: DATABASE_URL
scope: RUN_AND_BUILD_TIME
value: ${DB_CONNECTION_STRING} # Fetched from a linked database or secret
static_sites:
- name: frontend-site
github:
repo: your-github-username/your-frontend-repo
branch: main
build_command: npm install && npm run build
output_dir: build
routes:
- path: /
workers:
- name: queue-processor
github:
repo: your-github-username/your-worker-repo
branch: main
build_command: npm install && npm run build
run_command: node dist/worker.js
envs:
- key: REDIS_URL
value: ${REDIS_CONNECTION_STRING} # Link to a Redis service or secret
functions:
- name: image-resizer
github:
repo: your-github-username/your-functions-repo
branch: main
source_dir: functions/image-resizer # Directory containing function source
routes:
- path: /resize-image
Explanation: This spec defines an API, a frontend, a background worker, and a serverless function, each potentially from a different Git repository (or subdirectories of a monorepo). routes map paths to components, envs define environment variables, and build_command/run_command specify execution steps.
2. Managing Environment Variables and Secrets
Environment variables can be defined directly in app.yaml for non-sensitive values or managed via the DigitalOcean control panel or doctl for secrets. Secrets are automatically injected at runtime.
# app.yaml snippet for environment variables
services:
- name: my-service
envs:
- key: API_VERSION
value: v1.0
scope: BUILD_TIME # Only available during build
- key: FEATURE_FLAG_ENABLED
value: "true"
scope: RUN_TIME # Only available at runtime
- key: NODE_ENV
value: production
scope: RUN_AND_BUILD_TIME # Available for both
- key: DATABASE_PASSWORD # Referencing a secret
scope: RUN_TIME
value: ${DO_APP_DATABASE_PASSWORD}
Using doctl for Secrets:
For sensitive data like API keys or database passwords, avoid hardcoding them in app.yaml if it's committed to a public or shared repository. Instead, manage them as application-level secrets.
# Set a secret variable named MY_API_KEY for your app 'my-app'
doctl apps env set my-app MY_API_KEY --value "super-secret-key-123" --secret
# Set a database connection string as a secret
doctl apps env set my-app DB_CONNECTION_STRING --value "postgres://user:pass@host:port/db" --secret
# View environment variables (secrets are hidden)
doctl apps env list my-app
Explanation: When you set a secret with doctl, it's securely stored and injected into your application's environment as DATABASE_PASSWORD or DB_CONNECTION_STRING (matching the key you defined in app.yaml or set via doctl). The ${VAR_NAME} syntax in app.yaml is for referencing these.
3. Integrating with DigitalOcean Managed Databases
App Platform seamlessly integrates with DigitalOcean Managed Databases (PostgreSQL, MySQL, Redis, MongoDB). You link them by name, and App Platform automatically injects connection details as environment variables.
# app.yaml snippet for database integration
databases:
- name: my-postgres-db # Must match the name of an existing Managed Database
engine: PG
version: "14"
production: true
# This automatically creates environment variables like
# DO_APP_DATABASE_URL, DO_APP_DATABASE_USERNAME, etc.
# You can also reference a specific property:
# envs:
# - key: DATABASE_URL
# value: ${my-postgres-db.CONNECTION_STRING} # Reference by database name and property
services:
- name: api-service
github:
repo: your-github-username/your-api-repo
branch: main
envs:
- key: DATABASE_URL
value: ${my-postgres-db.CONNECTION_STRING} # Inject full connection string
- key: DB_HOST
value: ${my-postgres-db.HOSTNAME}
- key: DB_USER
value: ${my-postgres-db.USERNAME}
Explanation: By listing a database component, App Platform makes its connection details available to other components within the same app. You can reference specific properties like CONNECTION_STRING, HOSTNAME, USERNAME, etc., using the syntax ${database_name.PROPERTY_NAME}.
Best Practices
- Use
app.yamlfor Infrastructure-as-Code (IaC): Define your entire application stack inapp.yamland commit it to your repository. This ensures version control, repeatability, and easier collaboration. - Store Secrets Securely: Never commit sensitive API keys, database credentials, or private tokens directly into your
app.yamlor code repository. Usedoctl apps env set --secretor the DigitalOcean control panel to manage secrets, which App Platform injects at runtime. - Implement Robust Health Checks: Configure health check paths (
health_check_pathfor web services) to ensure App Platform correctly determines the health and readiness of your application instances before routing traffic. - Leverage Managed Databases: Integrate with DigitalOcean Managed Databases for reliable, scalable, and secure data storage. App Platform handles the secure injection of connection strings.
- Optimize Build Processes: Keep your
build_commandefficient. Cache dependencies (e.g.,node_modules) if possible, and only include necessary files in your deployment artifact to speed up builds and reduce deployment times. - Monitor Logs and Metrics: Regularly check your application logs and performance metrics (available in the DigitalOcean control panel) to identify issues, track performance, and inform scaling decisions.
- Utilize Private Networking: For internal services or workers that only communicate within your App Platform application, configure them to use private networking where possible to enhance security and reduce latency.
Anti-Patterns
- Hardcoding Secrets in
app.yaml: Committing API keys, database passwords, or other sensitive information directly into yourapp.yamlor source code.- Instead: Use DigitalOcean's secret management capabilities via
doctlor the control panel.
- Instead: Use DigitalOcean's secret management capabilities via
- Manual Deployments Only: Relying solely on manual deployments through the control panel for production applications.
- Instead: Leverage
deploy_on_push: truefor Git-driven automatic deployments and integratedoctlinto your CI/CD pipeline for programmatic updates.
- Instead: Leverage
- Ignoring Health Checks: Not defining or properly configuring health checks for your web services.
- Instead: Set up a
/healthor/statusendpoint and configurehealth_check_pathto ensure App Platform only routes traffic to healthy instances.
- Instead: Set up a
- Over-Provisioning Resources from the Start: Deploying with unnecessarily large instance sizes or counts without validated performance needs.
- Instead: Start with smaller, cost-effective instance sizes and scale up or out based on actual load and performance monitoring.
- Mixing Build and Run Environment Variables Carelessly: Not differentiating between
BUILD_TIMEandRUN_TIMEscopes for environment variables.- **Instead
Install this skill directly: skilldb add deployment-hosting-services-skills
Related Skills
AWS Lightsail
AWS Lightsail provides a simplified way to launch virtual private servers (VPS), containers, databases, and more. It's ideal for developers and small businesses needing easy-to-use, cost-effective cloud resources without deep AWS expertise.
Cloudflare Pages Deployment
Cloudflare Pages and Workers expertise — edge-first deployments, full-stack apps with Workers functions, KV/D1/R2 bindings, preview URLs, custom domains, and global CDN distribution
Coolify Deployment
Coolify self-hosted PaaS expertise — Docker-based deployments, Git integration, automatic SSL, database provisioning, server management, and Heroku/Netlify alternative on your own hardware
Fly.io Deployment
Fly.io platform expertise — container deployment, global edge distribution, Dockerfiles, volumes, secrets, scaling, PostgreSQL, and multi-region patterns
Google Cloud Run
Google Cloud Run is a fully managed serverless platform for containerized applications. It allows you to deploy stateless containers that scale automatically from zero to thousands of instances based on request load, paying only for the resources consumed. Choose Cloud Run for microservices, web APIs, and event-driven functions that require custom runtimes or environments.
Kamal
Kamal (formerly MRSK) simplifies deploying web applications to servers via SSH, leveraging Docker and Traefik (or Caddy) for zero-downtime, rolling updates. It's ideal for containerized applications on a single server or small cluster without the complexity of Kubernetes.