docs(local-dev): add 'Local development' section + PHP 8.5 support
All checks were successful
Build and deploy / deploy (push) Successful in 23s
All checks were successful
Build and deploy / deploy (push) Successful in 23s
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.
This commit is contained in:
@@ -15,6 +15,7 @@ export default defineConfig({
|
|||||||
'/whp/getting-started/': '/whp/getting-started/welcome/',
|
'/whp/getting-started/': '/whp/getting-started/welcome/',
|
||||||
'/whp/how-to/': '/whp/how-to/add-a-domain/',
|
'/whp/how-to/': '/whp/how-to/add-a-domain/',
|
||||||
'/whp/site-builder/': '/whp/site-builder/overview/',
|
'/whp/site-builder/': '/whp/site-builder/overview/',
|
||||||
|
'/whp/local-dev/': '/whp/local-dev/overview/',
|
||||||
'/whp/reference/': '/whp/reference/service-hostnames/',
|
'/whp/reference/': '/whp/reference/service-hostnames/',
|
||||||
'/whp/add-ons/': '/whp/add-ons/overview/',
|
'/whp/add-ons/': '/whp/add-ons/overview/',
|
||||||
'/whp/admin/': '/whp/admin/overview/',
|
'/whp/admin/': '/whp/admin/overview/',
|
||||||
@@ -65,6 +66,10 @@ export default defineConfig({
|
|||||||
badge: { text: 'Beta', variant: 'tip' },
|
badge: { text: 'Beta', variant: 'tip' },
|
||||||
items: [{ autogenerate: { directory: 'whp/site-builder' } }],
|
items: [{ autogenerate: { directory: 'whp/site-builder' } }],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Local development',
|
||||||
|
items: [{ autogenerate: { directory: 'whp/local-dev' } }],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Reference',
|
label: 'Reference',
|
||||||
items: [{ autogenerate: { directory: 'whp/reference' } }],
|
items: [{ autogenerate: { directory: 'whp/reference' } }],
|
||||||
|
|||||||
169
src/content/docs/whp/local-dev/node.mdx
Normal file
169
src/content/docs/whp/local-dev/node.mdx
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
---
|
||||||
|
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 />
|
||||||
50
src/content/docs/whp/local-dev/overview.mdx
Normal file
50
src/content/docs/whp/local-dev/overview.mdx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
title: Develop locally with our containers
|
||||||
|
description: Run the same Apache/PHP and Node containers locally that we use to host your site in production.
|
||||||
|
sidebar:
|
||||||
|
order: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
import Support from '~/content/partials/support-link.mdx';
|
||||||
|
|
||||||
|
The same container images we use to host your site in production are published as open-source images you can pull and run on your laptop. If you're comfortable with Docker, this gives you a development environment that matches production exactly — same OS, same Apache/Nginx config, same PHP or Node version.
|
||||||
|
|
||||||
|
## Why use our containers locally
|
||||||
|
|
||||||
|
- **Dev/prod parity.** Anything that runs in the container on your machine will run the same way in production. No "works on my Mac" surprises.
|
||||||
|
- **Quick start.** Each container ships a `local-dev.sh` script that handles the Docker incantation, volume layout, and helper commands.
|
||||||
|
- **No account required.** The images are public — pull and run.
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
This page is for customers who are comfortable with Docker. You don't need to use these images to host with us — the WHP panel handles everything for the hosted version. This is for **local development** only.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Available containers
|
||||||
|
|
||||||
|
| Stack | Image | Use case |
|
||||||
|
|---|---|---|
|
||||||
|
| **PHP + Apache** | `repo.anhonesthost.net/cloud-hosting-platform/cac` | WordPress, Laravel, traditional PHP apps |
|
||||||
|
| **Node + Nginx** | `repo.anhonesthost.net/cloud-hosting-platform/cnoc` | Express, custom Node apps, PM2-managed processes |
|
||||||
|
|
||||||
|
Both images live in our public Gitea organisation at [repo.anhonesthost.net/cloud-hosting-platform/](https://repo.anhonesthost.net/cloud-hosting-platform/) — the source Dockerfiles, build configs, and helper scripts are all there too. Issues and PRs welcome.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **Docker** (or a compatible runtime like Podman / OrbStack / Rancher Desktop). Docker Desktop on Mac/Windows or `docker.io` on Linux both work.
|
||||||
|
- A terminal where you can run `git`, `docker`, and basic shell scripts.
|
||||||
|
- Ports `80` and `443` free on your machine (the local-dev scripts bind these by default; both can be overridden with flags).
|
||||||
|
|
||||||
|
## Pick your stack
|
||||||
|
|
||||||
|
- **[PHP + Apache locally](/whp/local-dev/php-apache/)** — for WordPress and any PHP application.
|
||||||
|
- **[Node + Nginx locally](/whp/local-dev/node/)** — for Express, Next.js standalone, or any Node app.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Create a site](/whp/how-to/create-a-site/) — how the same images run as hosted sites in WHP.
|
||||||
|
- [What is containerized hosting?](/whp/getting-started/what-is-containerized-hosting/)
|
||||||
|
|
||||||
|
## Still stuck?
|
||||||
|
|
||||||
|
<Support />
|
||||||
155
src/content/docs/whp/local-dev/php-apache.mdx
Normal file
155
src/content/docs/whp/local-dev/php-apache.mdx
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
---
|
||||||
|
title: PHP + Apache locally
|
||||||
|
description: Run the cloud-apache-container image on your laptop for WordPress and other PHP apps.
|
||||||
|
sidebar:
|
||||||
|
order: 2
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Steps, Aside } from '@astrojs/starlight/components';
|
||||||
|
import Support from '~/content/partials/support-link.mdx';
|
||||||
|
|
||||||
|
[`cloud-apache-container`](https://repo.anhonesthost.net/cloud-hosting-platform/cloud-apache-container) (image: **`cac`**) is the same Apache + PHP image we use for hosted PHP sites. It's based on **AlmaLinux 9**, ships with **PHP 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, and 8.5** side-by-side (default 8.3), and uses **Apache with mod_ssl**.
|
||||||
|
|
||||||
|
## Image tags
|
||||||
|
|
||||||
|
Pre-built tags are pushed on every change:
|
||||||
|
|
||||||
|
- `cac:latest` — the default (PHP 8.3).
|
||||||
|
- `cac:php74`, `cac:php80`, `cac:php81`, `cac:php82`, `cac:php83`, `cac:php84`, `cac:php85` — pin to a specific PHP version.
|
||||||
|
|
||||||
|
Pull from `repo.anhonesthost.net/cloud-hosting-platform/cac:<tag>`.
|
||||||
|
|
||||||
|
## Quick start with `local-dev.sh`
|
||||||
|
|
||||||
|
The repo ships a `local-dev.sh` script that handles the Docker incantation, creates the volume + log directories, generates helper scripts, and installs a fresh WordPress in the web root.
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
1. Clone the repo and `cd` in:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://repo.anhonesthost.net/cloud-hosting-platform/cloud-apache-container.git
|
||||||
|
cd cloud-apache-container
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Start a local instance:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./local-dev.sh -n local-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
3. The script will:
|
||||||
|
- Create a user directory and log folders (`apache/`, `system/`).
|
||||||
|
- Create a Docker volume for MySQL.
|
||||||
|
- Start the container with the right env vars.
|
||||||
|
- Generate helper scripts in your root path (`instance_start`, `instance_stop`, `instance_logs`, `instance_db_info`).
|
||||||
|
- Install WordPress in your web root.
|
||||||
|
- Print the MySQL credentials it generated.
|
||||||
|
|
||||||
|
4. Open `http://localhost/` in a browser — WordPress's setup screen should be there.
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## Flags
|
||||||
|
|
||||||
|
| Flag | Purpose | Default |
|
||||||
|
|---|---|---|
|
||||||
|
| `-n` | Container name (required) | — |
|
||||||
|
| `-p` | HTTP port | `80` |
|
||||||
|
| `-s` | HTTPS port | `443` |
|
||||||
|
| `-r` | Root path for files and DB | current directory |
|
||||||
|
| `-a` | PHP version (`74`, `80`, `81`, `82`, `83`, `84`, `85`) | `83` |
|
||||||
|
| `-v` | Verbose mode | off |
|
||||||
|
| `-h` | Show help | — |
|
||||||
|
|
||||||
|
Example — run a PHP 8.5 instance on port 8080:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./local-dev.sh -n my-php85-site -a 85 -p 8080 -s 8443
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manual Docker usage
|
||||||
|
|
||||||
|
If you'd rather skip the script and run it yourself:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p local-development/domain.tld
|
||||||
|
cd local-development/domain.tld
|
||||||
|
mkdir user
|
||||||
|
mkdir -p user/logs/{apache,system}
|
||||||
|
|
||||||
|
docker run -d -it \
|
||||||
|
-p 80:80 -p 443:443 \
|
||||||
|
-e PHPVER=84 -e environment=DEV \
|
||||||
|
--mount type=bind,source="$(pwd)"/user,target=/home/myuser \
|
||||||
|
-v"$name-mysql":/var/lib/mysql \
|
||||||
|
-e uid=30001 -e user=myuser -e domain=localhost \
|
||||||
|
--name local-dev \
|
||||||
|
repo.anhonesthost.net/cloud-hosting-platform/cac:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get a shell inside the container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it local-dev /bin/bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful for running `wp-cli`, tailing logs from inside, or checking PHP modules.
|
||||||
|
|
||||||
|
## Where things live
|
||||||
|
|
||||||
|
| Inside the container | On your laptop (via bind mount) |
|
||||||
|
|---|---|
|
||||||
|
| `/home/myuser/public_html/` — Apache docroot | `local-development/domain.tld/user/public_html/` |
|
||||||
|
| `/home/myuser/logs/apache/` — Apache logs | `local-development/domain.tld/user/logs/apache/` |
|
||||||
|
| `/var/lib/mysql/` — MySQL data | Named Docker volume (`<name>-mysql`) |
|
||||||
|
| `/home/myuser/mysql_creds` | Same path on the bind mount |
|
||||||
|
|
||||||
|
## WordPress
|
||||||
|
|
||||||
|
`local-dev.sh` installs WordPress automatically. If you started manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it local-dev bash
|
||||||
|
cat /home/myuser/mysql_creds # see the credentials
|
||||||
|
cd /home/myuser/public_html
|
||||||
|
wp core download
|
||||||
|
wp config create --dbname=... --dbuser=... --dbpass=... --dbhost=localhost
|
||||||
|
wp core install --url=http://localhost --title="Local Dev" --admin_user=admin --admin_email=you@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stop / start / clean up
|
||||||
|
|
||||||
|
The helper scripts the local-dev script writes are the easy path:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./instance_stop # stop the container
|
||||||
|
./instance_start # start it again
|
||||||
|
./instance_logs # tail Apache logs
|
||||||
|
./instance_db_info # show MySQL credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
To wipe everything:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker rm -f local-dev
|
||||||
|
docker volume rm local-dev-mysql
|
||||||
|
rm -rf local-development/
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
Want to test the exact PHP version of your hosted WHP site locally? Match the `-a` flag to your site's PHP version on the [Sites page](/whp/how-to/create-a-site/).
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
[`cloud-apache-container` on Gitea](https://repo.anhonesthost.net/cloud-hosting-platform/cloud-apache-container) — Dockerfile, entrypoint, build configs, and the `local-dev.sh` script.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Node + Nginx locally](/whp/local-dev/node/)
|
||||||
|
- [Create a site](/whp/how-to/create-a-site/) — the hosted side.
|
||||||
|
|
||||||
|
## Still stuck?
|
||||||
|
|
||||||
|
<Support />
|
||||||
Reference in New Issue
Block a user