- 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>
275 lines
7.0 KiB
Markdown
275 lines
7.0 KiB
Markdown
# User Guide: Deploying Applications with Cloud Node Container
|
|
|
|
## Quick Start (For Non-Node.js Users)
|
|
|
|
If you've never used Node.js before, don't worry! This container makes it simple.
|
|
|
|
### What You Need to Know
|
|
|
|
**Node.js** is like PHP, but for JavaScript. Instead of Apache serving PHP files, your JavaScript code runs as a server application.
|
|
|
|
**Express.js** is like a web framework (similar to Laravel for PHP) that makes it easy to handle web requests.
|
|
|
|
### Basic Workflow Comparison
|
|
|
|
| PHP/Apache Workflow | Node.js Container Workflow |
|
|
|---------------------|---------------------------|
|
|
| Put `.php` files in web directory | Put `.js` files in `user/app/` |
|
|
| Apache serves files directly | Express.js handles requests |
|
|
| Database connection in each file | Server runs continuously |
|
|
| `<?php echo "Hello"; ?>` | `res.send("Hello")` |
|
|
|
|
## Step-by-Step: Deploy Your First App
|
|
|
|
### 1. Create Your Application Files
|
|
|
|
Create these two files in your `user/app/` directory:
|
|
|
|
**File: `package.json`**
|
|
```json
|
|
{
|
|
"name": "my-first-app",
|
|
"version": "1.0.0",
|
|
"main": "server.js",
|
|
"scripts": {
|
|
"start": "node server.js"
|
|
},
|
|
"dependencies": {
|
|
"express": "^4.18.2"
|
|
}
|
|
}
|
|
```
|
|
|
|
**File: `server.js`**
|
|
```javascript
|
|
const express = require('express');
|
|
const app = express();
|
|
const port = process.env.PORT || 3000;
|
|
|
|
// Serve static files (HTML, CSS, images) from 'public' folder
|
|
app.use(express.static('public'));
|
|
|
|
// Route for home page
|
|
app.get('/', (req, res) => {
|
|
res.send(`
|
|
<h1>Welcome to My Website!</h1>
|
|
<p>This is running on Node.js</p>
|
|
<a href="/about">About Page</a>
|
|
`);
|
|
});
|
|
|
|
// Route for about page
|
|
app.get('/about', (req, res) => {
|
|
res.send(`
|
|
<h1>About Us</h1>
|
|
<p>This website is powered by Node.js and Express</p>
|
|
<a href="/">Back to Home</a>
|
|
`);
|
|
});
|
|
|
|
// Health check (required by container)
|
|
app.get('/ping', (req, res) => {
|
|
res.json({ status: 'ok', timestamp: new Date() });
|
|
});
|
|
|
|
// Start the server
|
|
app.listen(port, () => {
|
|
console.log(`Server running on port ${port}`);
|
|
});
|
|
```
|
|
|
|
### 2. Start Your Container
|
|
|
|
```bash
|
|
./local-dev.sh -n my-first-app
|
|
```
|
|
|
|
### 3. Access Your Site
|
|
|
|
Visit `https://localhost` (accept the SSL warning) and you'll see your website!
|
|
|
|
## Common Use Cases
|
|
|
|
### Static Website (Like HTML/CSS sites)
|
|
|
|
Put your HTML files in `user/app/public/` and use this simple server:
|
|
|
|
```javascript
|
|
const express = require('express');
|
|
const app = express();
|
|
|
|
app.use(express.static('public'));
|
|
app.get('/ping', (req, res) => res.json({ status: 'ok' }));
|
|
|
|
app.listen(3000, () => console.log('Static site running'));
|
|
```
|
|
|
|
### Form Processing (Like PHP forms)
|
|
|
|
```javascript
|
|
const express = require('express');
|
|
const app = express();
|
|
|
|
app.use(express.urlencoded({ extended: true })); // Process form data
|
|
app.use(express.static('public'));
|
|
|
|
// Show contact form
|
|
app.get('/contact', (req, res) => {
|
|
res.send(`
|
|
<form method="POST" action="/contact">
|
|
<input name="name" placeholder="Your Name" required>
|
|
<input name="email" type="email" placeholder="Email" required>
|
|
<textarea name="message" placeholder="Message" required></textarea>
|
|
<button type="submit">Send</button>
|
|
</form>
|
|
`);
|
|
});
|
|
|
|
// Process form submission
|
|
app.post('/contact', (req, res) => {
|
|
const { name, email, message } = req.body;
|
|
|
|
// Here you would save to database, send email, etc.
|
|
console.log('Contact form:', { name, email, message });
|
|
|
|
res.send(`<h1>Thanks ${name}!</h1><p>We received your message.</p>`);
|
|
});
|
|
|
|
app.get('/ping', (req, res) => res.json({ status: 'ok' }));
|
|
app.listen(3000);
|
|
```
|
|
|
|
### Database Connection (Like MySQL in PHP)
|
|
|
|
```javascript
|
|
const express = require('express');
|
|
const app = express();
|
|
|
|
// In package.json dependencies, add: "mysql2": "^3.6.0"
|
|
const mysql = require('mysql2');
|
|
|
|
const db = mysql.createConnection({
|
|
host: 'localhost',
|
|
user: 'your_user',
|
|
password: 'your_password',
|
|
database: 'your_database'
|
|
});
|
|
|
|
app.get('/users', (req, res) => {
|
|
db.query('SELECT * FROM users', (err, results) => {
|
|
if (err) {
|
|
res.status(500).json({ error: err.message });
|
|
} else {
|
|
res.json(results);
|
|
}
|
|
});
|
|
});
|
|
|
|
app.get('/ping', (req, res) => res.json({ status: 'ok' }));
|
|
app.listen(3000);
|
|
```
|
|
|
|
## File Structure Examples
|
|
|
|
### Simple Website
|
|
```
|
|
user/app/
|
|
├── package.json
|
|
├── server.js
|
|
└── public/
|
|
├── index.html
|
|
├── about.html
|
|
├── style.css
|
|
└── images/
|
|
└── logo.png
|
|
```
|
|
|
|
### API Application
|
|
```
|
|
user/app/
|
|
├── package.json
|
|
├── server.js
|
|
├── routes/
|
|
│ ├── users.js
|
|
│ └── products.js
|
|
└── public/
|
|
└── api-docs.html
|
|
```
|
|
|
|
## Key Differences from PHP
|
|
|
|
| Concept | PHP | Node.js |
|
|
|---------|-----|---------|
|
|
| **File serving** | Apache serves .php files directly | Express routes handle requests |
|
|
| **Variables** | `$variable` | `let variable` |
|
|
| **Arrays** | `$arr = array()` | `let arr = []` |
|
|
| **Echo/Print** | `echo "Hello"` | `res.send("Hello")` |
|
|
| **Include files** | `include 'file.php'` | `require('./file.js')` |
|
|
| **Database** | Connect in each file | Connect once, reuse connection |
|
|
| **Sessions** | `$_SESSION` | `req.session` (with middleware) |
|
|
| **Forms** | `$_POST` | `req.body` (with middleware) |
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues for PHP Users
|
|
|
|
**Issue:** "Cannot GET /" error
|
|
**Solution:** Make sure you have an `app.get('/', ...)` route defined
|
|
|
|
**Issue:** Static files (CSS/images) not loading
|
|
**Solution:** Put them in `public/` folder and add `app.use(express.static('public'))`
|
|
|
|
**Issue:** Forms not working
|
|
**Solution:** Add `app.use(express.urlencoded({ extended: true }))` before your routes
|
|
|
|
**Issue:** App crashes on restart
|
|
**Solution:** PM2 will automatically restart it, but check logs in `user/logs/nodejs/`
|
|
|
|
### Getting Help
|
|
|
|
- Check container logs: `./instance_logs`
|
|
- Check your app specifically: `docker exec -it your-container-name pm2 logs`
|
|
- Access container shell: `./instance_shell`
|
|
- Health check: Visit `/ping` to see if your app is responding
|
|
|
|
## Advanced Features
|
|
|
|
### Using Sessions (like PHP $_SESSION)
|
|
|
|
```javascript
|
|
// Add to package.json dependencies: "express-session": "^1.17.3"
|
|
const session = require('express-session');
|
|
|
|
app.use(session({
|
|
secret: 'your-secret-key',
|
|
resave: false,
|
|
saveUninitialized: false
|
|
}));
|
|
|
|
app.get('/login', (req, res) => {
|
|
req.session.user = 'john_doe';
|
|
res.send('Logged in!');
|
|
});
|
|
|
|
app.get('/profile', (req, res) => {
|
|
if (req.session.user) {
|
|
res.send(`Hello ${req.session.user}!`);
|
|
} else {
|
|
res.send('Please log in');
|
|
}
|
|
});
|
|
```
|
|
|
|
### File Uploads
|
|
|
|
```javascript
|
|
// Add to package.json: "multer": "^1.4.5-lts.1"
|
|
const multer = require('multer');
|
|
const upload = multer({ dest: 'uploads/' });
|
|
|
|
app.post('/upload', upload.single('file'), (req, res) => {
|
|
res.send(`File uploaded: ${req.file.originalname}`);
|
|
});
|
|
```
|
|
|
|
The container handles all the complex server setup, so you can focus on building your application! |