Cloud Node Container
This is a base container for running Node.js applications, supporting multiple Node.js versions (18, 20, 22). The default is Node.js 20. The container is based on AlmaLinux 9 and uses Nginx as a reverse proxy with SSL. It is designed for both development and production use.
You must have Docker or compatible containerization software running.
What's Included?
- Multiple Node.js Versions: 18, 20, 22 (set with 
NODEVERor-aflag) - PM2 Process Manager: For production-grade Node.js application management
 - Nginx Reverse Proxy: SSL-enabled reverse proxy with automatic HTTP to HTTPS redirect
 - Development Features: Memcached for sessions, automatic backups, log rotation
 - Health Monitoring: Built-in 
/pingendpoint for health checks 
Quick Start: Local Development with local-dev.sh
The easiest way to start a local development environment is with the provided local-dev.sh script. This script automates container setup, volume creation, log directories, and creates a sample Node.js application.
Usage Example
./local-dev.sh -n local-dev
Flags:
-nName of the container (required)-pHTTP port (default: 80)-sHTTPS port (default: 443)-rRoot path for files (default: current directory)-aNode.js version (default: 20; options: 18, 20, 22)-vEnable verbose mode-hShow help
The script will:
- Create a user directory and log folders
 - Create a default Node.js Express application if none exists
 - Start the container with the correct environment variables
 - Generate helper scripts in your root path:
instance_start– Start the containerinstance_stop– Stop the containerinstance_logs– View container logsinstance_shell– Access container shell
 
Manual Docker Usage
You can also run the container manually:
mkdir -p local-development/domain.tld
cd local-development/domain.tld
mkdir user
mkdir -p user/{app,logs/{nginx,nodejs}}
docker run -d -p 80:80 -p 443:443 -e NODEVER=20 -e environment=DEV --mount type=bind,source="$(pwd)"/user,target=/home/$(whoami) -e uid=$(id -u) -e user=$(whoami) -e domain=localhost --name local-dev repo.anhonesthost.net/cloud-hosting-platform/cnoc:latest
Accessing the Container
docker exec -it local-dev /bin/bash
For Users: How to Deploy Your Application
Step 1: Prepare Your Node.js Application
Your Node.js application needs just two files to get started:
Required Files:
package.json- Describes your app and its dependencies- A main JavaScript file (usually 
server.jsorindex.js) 
Optional Files:
public/folder for static files (HTML, CSS, images)ecosystem.config.jsfor advanced PM2 configuration (auto-generated if not provided)
Step 2: What Users Need to Do
If you're not familiar with Node.js, here's what you need to know:
- Create a 
package.jsonfile - This tells Node.js about your app: 
{
  "name": "my-website",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}
- Create your main server file - This runs your application:
 
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.use(express.static('public')); // Serve static files
app.get('/', (req, res) => {
  res.send('<h1>My Website is Running!</h1>');
});
app.get('/ping', (req, res) => {
  res.json({ status: 'ok' }); // Health check for the container
});
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
- 
Put your files in the right place:
- Copy your 
package.jsonandserver.jstouser/app/ - Put HTML, CSS, images in 
user/app/public/ 
 - Copy your 
 - 
Start the container:
 
./local-dev.sh -n my-app
That's it! The container will:
- Install your dependencies automatically
 - Generate PM2 configuration from your package.json
 - Start your application with PM2
 - Handle SSL and reverse proxy
 - Provide health monitoring
 
Important package.json fields:
- name: Used as the PM2 process name (defaults to 'node-app')
 - main: Entry point file (defaults to 'index.js')
 - scripts.start: Alternative way to specify entry point (e.g., "node server.js")
 
The container automatically generates an ecosystem.config.js file from your package.json if you don't provide one.
PM2 Configuration Notes:
- The auto-generated PM2 config uses fork mode (not cluster mode) for simplicity and compatibility
 wait_readyis set tofalseby default - your app doesn't need to send any special signals to PM2- PM2 runs as the specified user (not root) for security - ensure your 
uidandusermatch your host system - If you need advanced PM2 features, you can provide your own 
ecosystem.config.jsfile 
Advanced Usage: If you want to use PM2's wait_ready feature for health checking:
- Create your own 
ecosystem.config.jswithwait_ready: true - Add 
process.send('ready')in your app when it's ready to accept connections:app.listen(port, () => { console.log(`Server running on port ${port}`); if (process.send) { process.send('ready'); } }); 
Step 3: Example Applications
See the examples/ directory for complete working examples:
Simple Website (examples/simple-website/):
- Static HTML pages with navigation
 - CSS styling
 - Express.js server for routing
 
API Server (examples/api-server/):
- REST API with CRUD operations
 - JSON responses
 - In-memory data storage
 
What Happens Automatically
When you place your app in user/app/, the container automatically:
- Runs 
npm installto install dependencies - Starts your app with PM2 process manager
 - Sets up Nginx reverse proxy with SSL
 - Configures logging and health checks
 - Starts Memcached for session storage (in DEV mode)
 
Troubleshooting for New Users
- App won't start? Check that your 
package.jsonhas a valid "start" script - Can't access your site? Make sure your app listens on port 3000 and has a 
/pingendpoint - Dependencies missing? List all required packages in your 
package.jsondependencies section - Static files not loading? Put them in a 
public/folder and useapp.use(express.static('public')) 
Features
- Multiple Node.js Versions: 18, 20, 22 (set with 
NODEVERenvironment variable) - Process Management: PM2 for production-grade Node.js application management
 - Reverse Proxy: Nginx handles SSL termination and proxies requests to Node.js
 - Automatic Backups: Application files backed up every 30 minutes in DEV mode
 - Log Management: Log rotation compresses logs older than 3 days, deletes after 7 days
 - Session Storage: Memcached available in DEV mode for session management
 - SSL: Self-signed certificate enabled by default with automatic HTTP→HTTPS redirect
 - Health Checks: 
/ping,/infoendpoints for monitoring - Static Files: Nginx serves static files from 
/home/$user/app/public/ 
Environment Variables
Required:
uid– User ID for file permissions (must match your host user ID)user– Username for file permissions (must match your host username)domain– Primary domain for configuration
Optional:
environment– Set toDEVto start Redis and enable development featuresserveralias– Comma-separated list of alternative hostnamesNODEVER– Node.js version (18, 20, 22)
Default Application Endpoints
The default Express.js application provides:
/– Basic application info and status/ping– Health check endpoint (JSON response)/info– Detailed system information/session– Session demo endpoint (shows Memcached sessions working)
Helpful Notes
- To restart the instance: 
./instance_startordocker start {container-name} - To stop: 
./instance_stopordocker stop {container-name} - To view logs: 
./instance_logsordocker logs -f {container-name} - To access shell: 
./instance_shellordocker exec -it {container-name} /bin/bash - To delete a container: 
docker rm {container-name}(does not delete user files) - Application logs are in 
/home/$user/logs/nodejs/ - Nginx logs are in 
/home/$user/logs/nginx/ 
System Requirements
Memory Requirements
- Minimum RAM: 256MB (basic applications)
 - Recommended RAM: 512MB (standard applications)
 - Development: 512MB-1GB (with all services enabled)
 
The container is optimized for memory efficiency with automatic memory management and process restarts. See MEMORY-GUIDE.md for detailed memory optimization information.
Performance Features
- Automatic application restart at 256MB memory usage
 - V8 heap limited to 200MB by default
 - Nginx optimized for single-worker, low-memory operation
 - Memcached limited to 32MB cache size
 
Troubleshooting
- The first run may take a few minutes as Node.js and dependencies are installed
 - If you need to change Node.js version, stop and remove the container, then recreate with the desired version
 - For custom applications, ensure your 
package.jsonhas a valid start script - Check 
/home/$user/logs/nodejs/error.logfor application errors - The health check endpoint 
/pingshould return a 200 status when the application is running properly - Memory issues: Run 
/scripts/memory-info.shinside container to check memory usage - Process monitoring: Use 
pm2 monitto watch application performance 
Common Issues and Solutions
502 Bad Gateway errors:
- Check if your app is running on port 3000 (or the PORT environment variable)
 - Look at nginx error logs: 
/home/$user/logs/nginx/error.log - Verify PM2 status: 
docker exec <container> su - <user> -c "pm2 status" 
Permission errors:
- Ensure 
uidanduserenvironment variables match your host system - Use 
$(id -u)and$(whoami)in your docker run command - Files should be owned by your user, not root
 
App not starting:
- Check PM2 logs: 
/home/$user/logs/nodejs/error.log - Verify your package.json has correct 
mainorscripts.startfield - Ensure all dependencies are listed in package.json