Complete Node.js container implementation with multi-version support
Some checks failed
Cloud Node Container / Build-and-Push (18) (push) Failing after 10s
Cloud Node Container / Build-and-Push (20) (push) Failing after 8s
Cloud Node Container / Build-and-Push (22) (push) Failing after 8s

- Add Dockerfile with AlmaLinux 9 base, Nginx reverse proxy, and PM2
- Support Node.js versions 18, 20, 22 with automated installation
- Implement memory-optimized configuration (256MB minimum, 512MB recommended)
- Add Memcached session storage for development environments
- Create comprehensive documentation (README, USER-GUIDE, MEMORY-GUIDE, CLAUDE.md)
- Include example applications (simple website and REST API)
- Add Gitea CI/CD pipeline for automated multi-version builds
- Provide local development script with helper utilities
- Implement health monitoring, log rotation, and backup systems

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-21 16:00:46 -07:00
parent 36285fa102
commit 2989cd590a
28 changed files with 1777 additions and 1 deletions

17
scripts/backup.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
USER=$1
BACKUP_DIR="/home/$USER/_backups"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup directory if it doesn't exist
mkdir -p $BACKUP_DIR
# Backup application files
tar -czf $BACKUP_DIR/app_backup_$DATE.tar.gz -C /home/$USER app/
# Keep only last 10 backups
cd $BACKUP_DIR
ls -t app_backup_*.tar.gz | tail -n +11 | xargs -r rm
echo "Backup completed: app_backup_$DATE.tar.gz"

54
scripts/create-nginx-config.sh Executable file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Create nginx configuration for reverse proxy to Node.js app
cat > /etc/nginx/conf.d/default.conf << EOF
upstream nodejs_backend {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name $domain $serveralias;
# Redirect HTTP to HTTPS
return 301 https://\$server_name\$request_uri;
}
server {
listen 443 ssl http2;
server_name $domain $serveralias;
ssl_certificate /etc/pki/tls/certs/localhost.crt;
ssl_certificate_key /etc/pki/tls/private/localhost.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
access_log /home/$user/logs/nginx/access.log;
error_log /home/$user/logs/nginx/error.log;
location / {
proxy_pass http://nodejs_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_cache_bypass \$http_upgrade;
}
location /ping {
proxy_pass http://nodejs_backend/ping;
access_log off;
}
# Static files
location /static/ {
alias /home/$user/app/public/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
EOF

68
scripts/entrypoint.sh Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
if [ -z "$NODEVER" ]; then
NODEVER="20";
fi
if [ -z "$environment" ]; then
environment="PROD"
fi
adduser -u $uid $user
mkdir -p /home/$user/app
mkdir -p /home/$user/logs/{nginx,nodejs}
# Link log directories
rm -rf /var/log/nginx
ln -s /home/$user/logs/nginx /var/log/nginx
ln -s /home/$user/logs/nodejs /var/log/nodejs
# Configure nginx for reverse proxy
/scripts/create-nginx-config.sh
# Set ownership and permissions
chown -R $user:$user /home/$user
chmod -R 755 /home/$user
# Start nginx
nginx
if [[ $environment == 'DEV' ]]; then
echo "Starting Dev Deployment"
mkdir -p /home/$user/_backups
# Ensure microdnf is available for installing additional packages in DEV mode
if ! command -v microdnf &> /dev/null; then
echo "microdnf not found, installing with dnf..."
dnf install -y microdnf && dnf clean all
fi
# Install Memcached for session storage in DEV mode with memory limit
microdnf install -y memcached
# Start memcached with 32MB memory limit
nohup memcached -d -u $user -p 11211 -m 32
# Set up automatic backups
echo "*/30 * * * * root /scripts/backup.sh $user" >> /etc/crontab
fi
# Start cron for log rotation and backups
/usr/sbin/crond
# If there's an app in the user directory, start it with PM2
if [ -f /home/$user/app/package.json ]; then
cd /home/$user/app
su -c "npm install" $user
su -c "pm2 start ecosystem.config.js" $user
else
# Start default app
cd /var/www/html
npm install
su -c "pm2 start ecosystem.config.js" $user
fi
# Follow logs
tail -f /home/$user/logs/nginx/* /home/$user/logs/nodejs/*
exit 0

6
scripts/install-node18.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
dnf install -y nodejs
npm install -g npm@latest
node --version
npm --version

6
scripts/install-node20.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
dnf install -y nodejs
npm install -g npm@latest
node --version
npm --version

6
scripts/install-node22.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
curl -fsSL https://rpm.nodesource.com/setup_22.x | bash -
dnf install -y nodejs
npm install -g npm@latest
node --version
npm --version

18
scripts/log-rotate.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Log rotation script for nginx and Node.js logs
LOG_DIR="/home/*/logs"
# Compress logs older than 3 days
find $LOG_DIR -name "*.log" -type f -mtime +3 -exec gzip {} \;
# Delete compressed logs older than 7 days
find $LOG_DIR -name "*.gz" -type f -mtime +7 -delete
# Rotate nginx logs
if [ -f /var/run/nginx.pid ]; then
kill -USR1 $(cat /var/run/nginx.pid)
fi
# Rotate PM2 logs
pm2 flush

58
scripts/memory-info.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env bash
echo "=== Cloud Node Container Memory Usage ==="
echo "Date: $(date)"
echo ""
echo "=== System Memory ==="
free -h
echo ""
echo "=== Process Memory Usage ==="
echo "Process PID VSZ RSS %MEM"
echo "----------------------------------------"
# Nginx
nginx_pid=$(pgrep nginx | head -1)
if [ ! -z "$nginx_pid" ]; then
ps -o pid,vsz,rss,%mem,comm -p $nginx_pid | tail -n +2 | while read pid vsz rss mem comm; do
printf "%-25s %5s %6s %6s %5s\n" "$comm" "$pid" "${vsz}K" "${rss}K" "$mem%"
done
fi
# Node.js/PM2
pm2_pids=$(pgrep -f "PM2\|node")
if [ ! -z "$pm2_pids" ]; then
echo "$pm2_pids" | while read pid; do
ps -o pid,vsz,rss,%mem,comm -p $pid 2>/dev/null | tail -n +2 | while read pid vsz rss mem comm; do
printf "%-25s %5s %6s %6s %5s\n" "$comm" "$pid" "${vsz}K" "${rss}K" "$mem%"
done
done
fi
# Memcached
memcached_pid=$(pgrep memcached)
if [ ! -z "$memcached_pid" ]; then
ps -o pid,vsz,rss,%mem,comm -p $memcached_pid | tail -n +2 | while read pid vsz rss mem comm; do
printf "%-25s %5s %6s %6s %5s\n" "$comm" "$pid" "${vsz}K" "${rss}K" "$mem%"
done
fi
echo ""
echo "=== Container Resource Limits ==="
if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then
limit=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
if [ $limit -lt 9223372036854775807 ]; then
echo "Memory Limit: $((limit / 1024 / 1024))MB"
else
echo "Memory Limit: No limit set"
fi
fi
echo ""
echo "=== PM2 Process Info ==="
if command -v pm2 &> /dev/null; then
pm2 list 2>/dev/null | grep -E "(App name|online|stopped|errored)"
echo ""
pm2 show 0 2>/dev/null | grep -E "(memory|cpu|uptime)" || echo "No PM2 processes running"
fi