Complete Node.js container implementation with multi-version support
- 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:
17
scripts/backup.sh
Executable file
17
scripts/backup.sh
Executable 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
54
scripts/create-nginx-config.sh
Executable 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
68
scripts/entrypoint.sh
Executable 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
6
scripts/install-node18.sh
Executable 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
6
scripts/install-node20.sh
Executable 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
6
scripts/install-node22.sh
Executable 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
18
scripts/log-rotate.sh
Executable 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
58
scripts/memory-info.sh
Executable 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
|
Reference in New Issue
Block a user