Production Cloud Deployment
Learn to deploy Node.js applications to various cloud platforms including AWS, Google Cloud, and Azure. This is a foundational concept in server-side JavaScript development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world Node.js experience. Take your time with each section and practice the examples
AWS Deployment
Deploy Node.js applications to AWS using services like ECS, Lambda, and Elastic Beanstalk.. This is an essential concept that every Node.js developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
AWS ECS Deployment
# task-definition.json
{
"family": "myapp-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::account:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::account:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "myapp",
"image": "myapp:latest",
"portMappings": [
{
"containerPort": 3000,
"protocol": "tcp"
}
],
"environment": [
{
"name": "NODE_ENV",
"value": "production"
}
],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:ssm:region:account:parameter/myapp/database-url"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3
}
}
]
}AWS Lambda Deployment
# serverless.yml for AWS Lambda
service: myapp
provider:
name: aws
runtime: nodejs18.x
region: us-east-1
environment:
NODE_ENV: production
iam:
role:
statements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: "arn:aws:dynamodb:us-east-1:*:table/myapp-*"
functions:
api:
handler: src/handler.api
events:
- http:
path: /{proxy+}
method: ANY
cors: true
timeout: 30
memorySize: 512
processData:
handler: src/handler.processData
events:
- schedule: rate(5 minutes)
timeout: 60
memorySize: 1024
plugins:
- serverless-offline
- serverless-dynamodb-local
custom:
serverless-offline:
httpPort: 3000
dynamodb:
start:
port: 8000
inMemory: true
migrate: trueGoogle Cloud Deployment
# app.yaml for Google App Engine
runtime: nodejs18
env_variables:
NODE_ENV: production
DATABASE_URL: "postgresql://user:password@/myapp?host=/cloudsql/project:region:instance"
automatic_scaling:
min_instances: 1
max_instances: 10
target_cpu_utilization: 0.6
handlers:
- url: /.*
script: auto
secure: always
# cloudbuild.yaml for Google Cloud Build
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/myapp', '.']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/myapp']
- name: 'gcr.io/cloud-builders/gcloud'
args: ['run', 'deploy', 'myapp', '--image', 'gcr.io/$PROJECT_ID/myapp', '--platform', 'managed', '--region', 'us-central1']Azure Deployment
# azure-pipelines.yml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
steps:
- task: NodeTool@0
inputs:
versionSpec: '18.x'
displayName: 'Install Node.js'
- script: |
npm install
npm run build
displayName: 'npm install and build'
- task: Docker@2
displayName: 'Build and push image'
inputs:
command: buildAndPush
repository: myapp
dockerfile: '$(Build.SourcesDirectory)/Dockerfile'
containerRegistry: 'myRegistry'
tags: |
$(Build.BuildId)
latest
- stage: Deploy
displayName: Deploy stage
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: Deploy
displayName: Deploy
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- task: AzureWebAppContainer@1
displayName: 'Azure Web App on Container Deploy'
inputs:
azureSubscription: 'mySubscription'
appName: 'myapp'
containers: 'myRegistry.azurecr.io/myapp:$(Build.BuildId)'Mini-Project: Multi-Cloud Deployment
# Complete multi-cloud deployment setup
# terraform/main.tf
provider "aws" {
region = var.aws_region
}
provider "google" {
project = var.gcp_project
region = var.gcp_region
}
# AWS ECS Cluster
resource "aws_ecs_cluster" "main" {
name = "myapp-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
}
# Google Cloud Run Service
resource "google_cloud_run_service" "main" {
name = "myapp"
location = var.gcp_region
template {
spec {
containers {
image = "gcr.io/${var.gcp_project} / myapp: latest"
ports {
container_port = 3000
}
env {
name = "NODE_ENV"
value = "production"
}
}
}
}
}
# Azure Container Instance
resource "azurerm_container_group" "main" {
name = "myapp"
location = var.azure_location
resource_group_name = var.azure_resource_group
os_type = "Linux"
container {
name = "myapp"
image = "myapp.azurecr.io/myapp:latest"
cpu = "0.5"
memory = "1.5"
ports {
port = 3000
protocol = "TCP"
}
environment_variables = {
NODE_ENV = "production"
}
}
}
# variables.tf
variable "aws_region" {
description = "AWS region"
type = string
default = "us-east-1"
}
variable "gcp_project" {
description = "GCP project ID"
type = string
}
variable "gcp_region" {
description = "GCP region"
type = string
default = "us-central1"
}
variable "azure_location" {
description = "Azure location"
type = string
default = "East US"
}
variable "azure_resource_group" {
description = "Azure resource group"
type = string
}