Files
kb-anhonesthost/src/content/docs/whp/local-dev/node.mdx
T
shadowdao 69439afe4a
Build and deploy / deploy (push) Successful in 23s
docs(local-dev): add 'Local development' section + PHP 8.5 support
Adds /whp/local-dev/ with three articles documenting the public cloud
container images on repo.anhonesthost.net/cloud-hosting-platform/:

- overview: dev/prod parity pitch, prerequisites, table of images,
  link to the Gitea org, and a note that this is for customers
  comfortable with Docker (the hosted side needs none of this).
- php-apache: cloud-apache-container (cac). PHP 7.4 through 8.5 side
  by side, default 8.3, AlmaLinux 9 + Apache mod_ssl. Documents
  image tags, local-dev.sh flags, manual docker command, bind-mount
  layout, WordPress install, helper scripts (instance_start /
  instance_stop / instance_logs / instance_db_info), and cleanup.
- node: cloud-node-container (cnoc). Node 18/20/22, default 20,
  AlmaLinux 9 + Nginx (SSL + HTTP→HTTPS redirect) + PM2 +
  Memcached. Same shape: tags, flags, manual docker, where code
  goes (user/app/), logs layout, helpers, cleanup.

Sidebar gains a 'Local development' group between Site Builder and
Reference. Section redirect /whp/local-dev/ -> overview added to
the section-landing redirect set.
2026-05-18 12:01:49 -07:00

170 lines
5.1 KiB
Plaintext

---
title: Node + Nginx locally
description: Run the cloud-node-container image on your laptop for Express, custom Node apps, and PM2-managed processes.
sidebar:
order: 3
---
import { Steps, Aside } from '@astrojs/starlight/components';
import Support from '~/content/partials/support-link.mdx';
[`cloud-node-container`](https://repo.anhonesthost.net/cloud-hosting-platform/cloud-node-container) (image: **`cnoc`**) is the same Node + Nginx image we use for hosted Node sites. It's based on **AlmaLinux 9**, ships with **Node 18, 20, and 22** side-by-side (default 20), uses **PM2** as the process manager, and fronts your app with **Nginx (SSL + HTTP→HTTPS redirect)**.
## What's included
- **Multiple Node versions** — 18, 20, 22, switchable via `NODEVER` env var or the `-a` flag.
- **PM2** for production-grade process management — automatic restart, log rotation.
- **Nginx reverse proxy** with SSL and HTTP→HTTPS redirect.
- **Memcached** for sessions, automatic backups, log rotation.
- **`/ping` health endpoint** baked into the proxy config.
## Image tags
Pull from `repo.anhonesthost.net/cloud-hosting-platform/cnoc:<tag>`. The most useful tags:
- `cnoc:latest` — the default (Node 20).
- Version-pinned tags follow the same pattern (`cnoc:node18`, `cnoc:node20`, `cnoc:node22`).
Check the repo for the current tag list.
## Quick start with `local-dev.sh`
The repo ships a `local-dev.sh` script that handles the Docker run, creates the bind-mount layout, generates helper scripts, and scaffolds a sample Express app if none exists.
<Steps>
1. Clone the repo and `cd` in:
```bash
git clone https://repo.anhonesthost.net/cloud-hosting-platform/cloud-node-container.git
cd cloud-node-container
```
2. Start a local instance:
```bash
./local-dev.sh -n local-dev
```
3. The script will:
- Create user + log directories (`nginx/`, `nodejs/`).
- Scaffold a default Express app under `user/app/` if you haven't dropped your own in yet.
- Start the container with the right env vars.
- Generate helper scripts (`instance_start`, `instance_stop`, `instance_logs`, `instance_shell`).
4. Open `http://localhost/` in a browser — the sample Express app's response page should be there. Or hit `http://localhost/ping` to confirm the health endpoint.
</Steps>
## Flags
| Flag | Purpose | Default |
|---|---|---|
| `-n` | Container name (required) | — |
| `-p` | HTTP port | `80` |
| `-s` | HTTPS port | `443` |
| `-r` | Root path for files | current directory |
| `-a` | Node version (`18`, `20`, `22`) | `20` |
| `-v` | Verbose mode | off |
| `-h` | Show help | — |
Example — run a Node 22 instance on port 3000:
```bash
./local-dev.sh -n my-node22-app -a 22 -p 3000 -s 3443
```
## Manual Docker usage
```bash
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
```
## Get a shell inside the container
```bash
docker exec -it local-dev /bin/bash
```
Useful for running `pm2 ls`, `pm2 logs`, or `npm` commands against your bind-mounted app folder.
## Where your code goes
Your Node application lives at `user/app/` on your laptop. Inside the container that's `/home/<user>/app/`. The container is configured to run your app from there via PM2.
Minimum required files in `user/app/`:
- **`package.json`** — describes your app and dependencies; **must define a start command** (`"start": "node server.js"` in `scripts`).
- **A main JavaScript file** — typically `server.js` or `index.js`.
After dropping files in, restart the container so PM2 picks up the new app:
```bash
docker restart local-dev
```
Your app should bind to the **port shown by the container's env var** (usually `process.env.PORT`). Nginx forwards traffic to that port internally and proxies SSL.
## Logs
| Where | What |
|---|---|
| `user/logs/nginx/` | Nginx access + error logs |
| `user/logs/nodejs/` | PM2's stdout/stderr capture from your Node app |
Tail them from your laptop:
```bash
tail -F user/logs/nodejs/*.log
```
Or via the helper script:
```bash
./instance_logs
```
## Stop / start / clean up
```bash
./instance_stop # stop the container
./instance_start # start it again
./instance_logs # view container logs
./instance_shell # exec into the container
```
To wipe everything:
```bash
docker rm -f local-dev
rm -rf local-development/
```
<Aside type="tip">
The `/ping` endpoint is wired by Nginx independently of your app — useful for `docker healthcheck` config when you start adapting the manual command to your own setup.
</Aside>
## Source
[`cloud-node-container` on Gitea](https://repo.anhonesthost.net/cloud-hosting-platform/cloud-node-container) — Dockerfile, Nginx + PM2 configs, entrypoint, and the `local-dev.sh` script.
## Related
- [PHP + Apache locally](/whp/local-dev/php-apache/)
- [Create a site](/whp/how-to/create-a-site/) — the hosted side.
## Still stuck?
<Support />