Deployment Guide¶
This guide covers deployment strategies for AMRnet, including local development, staging environments, and production deployment on various platforms.
Environment Setup¶
AMRnet supports multiple deployment environments with different configurations:
Development Environment¶
For local development with hot reloading and debugging:
# Clone and setup
git clone https://github.com/amrnet/amrnet.git
cd amrnet
# Install dependencies
npm install
cd client && npm install && cd ..
# Environment configuration
cp .env.example .env
Environment Variables (.env):
NODE_ENV=development
PORT=8080
# Database
MONGODB_URI=mongodb://localhost:27017/amrnet
# Development settings
REACT_APP_API_URL=http://localhost:8080/api/
ENABLE_DEBUG_LOGS=true
Start Development Servers:
# Start both backend and frontend
npm run start:dev
# Or individually:
npm run start:backend # Backend only (port 8080)
npm run client # Frontend only (port 3000)
Staging Environment¶
For testing production builds locally:
# Build production bundle
npm run build
# Start production server
NODE_ENV=production npm start
Production Deployment¶
Heroku Deployment¶
AMRnet is optimized for Heroku deployment with automatic build processes:
1. Heroku App Setup:
# Install Heroku CLI and login
heroku login
# Create new app
heroku create your-app-name
# Provision MongoDB (e.g., mLab sandbox or an external managed cluster).
# AMRnet production itself runs MongoDB on the same EC2 host as the app;
# Heroku is shown here as an alternative hosting path.
heroku addons:create mongolab:sandbox
2. Environment Configuration:
# Set environment variables
heroku config:set NODE_ENV=production
heroku config:set MONGODB_URI="your-mongodb-connection-string"
heroku config:set REACT_APP_API_URL="https://your-app-name.herokuapp.com/api/"
3. Deployment:
# Deploy to Heroku
git add .
git commit -m "Deploy to Heroku"
git push heroku main
# Monitor deployment
heroku logs --tail
Heroku Configuration Files:
Procfile:
web: node server.js
package.json (heroku-postbuild script):
{
"scripts": {
"heroku-postbuild": "cd client && npm install && npm run build"
}
}
MongoDB on EC2 Configuration¶
AMRnet production runs MongoDB locally on the application EC2 instance
(bound to 127.0.0.1 — no public listener). This keeps the data plane
off the public internet and avoids the cost and IP-allowlist maintenance
of a managed Atlas cluster.
1. Host Setup:
Install MongoDB 6.0+ on the EC2 instance
Keep
bindIp: 127.0.0.1in/etc/mongod.confEnable authentication and create a read/write user for AMRnet
Store the URI in
/opt/amrnet/.credentialswithchmod 600
2. Connection Configuration:
# Production .env (EC2) — loopback only
MONGODB_URI=mongodb://amrnet_user:password@127.0.0.1:27017/amrnet?authSource=admin
3. MongoDB Compass access (developer laptops):
# Open an SSH tunnel, then point Compass at localhost:27018
ssh -L 27018:127.0.0.1:27017 ec2-user@<host>
# See deploy/mongo-tunnel.sh for the wrapper script
3. Production Optimizations:
// config/db.js - Production MongoDB settings
const mongoOptions = {
useNewUrlParser: true,
useUnifiedTopology: true,
maxPoolSize: 10,
minPoolSize: 5,
maxIdleTimeMS: 30000,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
bufferMaxEntries: 0,
bufferCommands: false,
};
Docker Deployment¶
For containerized deployment:
Dockerfile:
# Multi-stage build for optimized production image
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Build client
COPY client/package*.json ./client/
WORKDIR /app/client
RUN npm ci --only=production
COPY client/ .
RUN npm run build
# Production stage
FROM node:18-alpine AS production
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/client/build ./client/build
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
docker-compose.yml:
version: '3.8'
services:
amrnet:
build: .
ports:
- "8080:8080"
environment:
- NODE_ENV=production
- MONGODB_URI=mongodb://mongo:27017/amrnet
depends_on:
- mongo
mongo:
image: mongo:6
ports:
- "27017:27017"
volumes:
- mongo_data:/data/db
volumes:
mongo_data:
Deployment Commands:
# Build and start containers
docker-compose up -d
# View logs
docker-compose logs -f amrnet
AWS Deployment¶
For AWS deployment using Elastic Beanstalk:
1. EB CLI Setup:
# Install EB CLI
pip install awsebcli
# Initialize EB application
eb init amrnet
# Create environment
eb create amrnet-production
2. Configuration Files:
.ebextensions/01_node_command.config:
option_settings:
aws:elasticbeanstalk:container:nodejs:
NodeCommand: "node server.js"
aws:elasticbeanstalk:application:environment:
NODE_ENV: production
3. Deploy:
# Deploy to AWS
eb deploy
# Monitor health
eb health
Performance Optimization¶
Production deployment optimizations for better performance:
Build Optimizations¶
Client Build Configuration:
// client/.env.production
GENERATE_SOURCEMAP=false
REACT_APP_NODE_ENV=production
// Build optimizations in package.json
{
"scripts": {
"build": "react-scripts build && npm run compress",
"compress": "gzip -k build/static/js/*.js && gzip -k build/static/css/*.css"
}
}
Server Optimizations¶
Express.js Production Configuration:
// server.js production settings
const express = require('express');
const compression = require('compression');
const helmet = require('helmet');
const app = express();
// Security middleware
app.use(helmet());
// Compression middleware
app.use(compression({
level: 6,
threshold: 1024,
}));
// Static file caching
app.use(express.static('client/build', {
maxAge: '1y',
etag: false
}));
Database Optimizations¶
MongoDB Production Indexes:
// Database indexes for production
db.ecoli_data.createIndex({ COUNTRY_ONLY: 1, YEAR: 1 });
db.kpneumo_data.createIndex({ GENOTYPE: 1, COUNTRY_ONLY: 1 });
db.styphi_data.createIndex({ GENOTYPE: 1, YEAR: 1, COUNTRY_ONLY: 1 });
Monitoring and Logging¶
Production monitoring setup for performance and error tracking:
Application Monitoring¶
Winston Logging Configuration:
// config/logger.js
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: { service: 'amrnet' },
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' }),
],
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}
Performance Monitoring Middleware:
// middleware/performance.js
const performanceMiddleware = (req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
logger.info(`${req.method} ${req.path}`, {
duration,
statusCode: res.statusCode,
ip: req.ip
});
// Alert on slow requests
if (duration > 2000) {
logger.warn(`Slow request detected: ${req.path} took ${duration}ms`);
}
});
next();
};
Error Tracking¶
Sentry Integration:
// Error tracking with Sentry
const Sentry = require('@sentry/node');
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
});
// Error handler middleware
app.use(Sentry.Handlers.errorHandler());
Health Checks¶
Application Health Endpoint:
// Health check endpoint
app.get('/health', async (req, res) => {
try {
// Check database connection
await mongoose.connection.db.admin().ping();
res.status(200).json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
database: 'connected'
});
} catch (error) {
res.status(503).json({
status: 'unhealthy',
error: error.message
});
}
});
Backup and Recovery¶
Data backup strategies for production environments:
Database Backups¶
EC2 Snapshot + mongodump Strategy:
Take AWS EBS snapshots of the MongoDB data volume on a schedule
Run periodic
mongodumpto an S3 bucket for logical backupsTest restoration into a staging instance regularly
Manual Backup Scripts:
#!/bin/bash
# backup-script.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/amrnet_$DATE"
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup each collection
mongodump --uri="$MONGODB_URI" --out=$BACKUP_DIR
# Compress backup
tar -czf "$BACKUP_DIR.tar.gz" -C /backups "amrnet_$DATE"
# Clean up uncompressed backup
rm -rf $BACKUP_DIR
# Upload to cloud storage (optional)
aws s3 cp "$BACKUP_DIR.tar.gz" s3://amrnet-backups/
Application Backups¶
Code and Configuration Backup:
# Git-based backup strategy
git tag -a "production-$(date +%Y%m%d)" -m "Production backup $(date)"
git push origin --tags
Security Considerations¶
Security best practices for production deployment:
Environment Security¶
Secure Environment Variables:
# Use secure credential management
heroku config:set MONGODB_URI="$(cat mongodb_uri.txt)"
# Rotate credentials regularly
heroku config:set SESSION_SECRET="$(openssl rand -base64 32)"
Network Security:
// CORS configuration
const cors = require('cors');
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(',') || 'https://amrnet.org',
credentials: true,
optionsSuccessStatus: 200
}));
Database Security¶
MongoDB Security:
Enable authentication and authorization
Use SSL/TLS for connections
Implement IP whitelisting
Regular security updates
Audit logging for database access
Troubleshooting¶
Common deployment issues and solutions:
Build Failures:
# Clear build cache
rm -rf node_modules package-lock.json
npm install
# Frontend build issues
cd client
rm -rf node_modules package-lock.json build
npm install
npm run build
Database Connection Issues:
# Test MongoDB connection
mongosh "your-mongodb-uri"
# Check network connectivity
ping cluster.mongodb.net
Performance Issues:
# Monitor resource usage
heroku ps:exec
top
# Check logs for errors
heroku logs --tail
Memory Issues:
# Increase Heroku dyno size
heroku ps:scale web=1:standard-2x
# Check memory usage patterns
heroku logs --source=heroku.router