183 lines
5.2 KiB
Markdown
183 lines
5.2 KiB
Markdown
# Docker Deployment To A Linux VServer
|
|
|
|
This repo now includes a deployment script for shipping `RolemasterDb.App` to a remote Linux server that you reach as `root`, for example with:
|
|
|
|
```bash
|
|
ssh myvserver
|
|
```
|
|
|
|
The intended public URL is:
|
|
|
|
```text
|
|
https://rolemasterdb.franktovar.de
|
|
```
|
|
|
|
The script publishes the app locally, uploads a release bundle over `scp`, builds the Docker image on the server, and replaces the running container. Nginx remains a one-time manual setup on the host and proxies to the container over localhost.
|
|
|
|
## Files
|
|
|
|
- `scripts/deploy-vserver.sh`
|
|
- `deploy/vserver.Dockerfile`
|
|
- `deploy/vserver.env.example`
|
|
|
|
## Remote Prerequisites
|
|
|
|
On the vserver:
|
|
|
|
1. Install Docker.
|
|
2. Install nginx.
|
|
3. Install a certificate tool such as `certbot` plus the nginx plugin if you want automated certificate provisioning.
|
|
4. Make sure `rolemasterdb.franktovar.de` resolves to this server. Your wildcard `A` and `AAAA` records already satisfy that.
|
|
|
|
The deploy script stores releases under `REMOTE_APP_DIR/releases/<timestamp>` and keeps the SQLite database in `REMOTE_DATA_DIR/rolemaster.db`.
|
|
The container should stay behind nginx, so the default deploy config binds it to `127.0.0.1:8080`.
|
|
|
|
## Local Setup
|
|
|
|
Create a local deploy config from the example:
|
|
|
|
```bash
|
|
cp deploy/vserver.env.example deploy/vserver.env
|
|
```
|
|
|
|
Adjust the values in `deploy/vserver.env` as needed:
|
|
|
|
- `REMOTE_HOST`: your SSH host or alias, for example `root@myvserver`
|
|
- `REMOTE_APP_DIR`: base directory on the server, default `/root/docker/rolemasterdb`
|
|
- `REMOTE_DATA_DIR`: persistent directory for the SQLite database
|
|
- `HOST_BIND_ADDRESS`: default `127.0.0.1` so only nginx can reach the container
|
|
- `HOST_PORT`: nginx upstream port on the host, default `8080`
|
|
- `REMOTE_USE_SUDO`: keep `0` when you deploy as `root`
|
|
- `REMOTE_ENV_FILE`: optional existing env file on the server to pass through to `docker run`
|
|
|
|
## One-Time Server Setup
|
|
|
|
Create the base directories on the server:
|
|
|
|
```bash
|
|
ssh myvserver
|
|
mkdir -p /root/docker/rolemasterdb/data
|
|
```
|
|
|
|
Deploy once so the container exists:
|
|
|
|
```bash
|
|
./scripts/deploy-vserver.sh
|
|
```
|
|
|
|
Create an nginx site config at `/etc/nginx/sites-available/rolemasterdb.franktovar.de`:
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name rolemasterdb.franktovar.de;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8080;
|
|
proxy_http_version 1.1;
|
|
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_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_read_timeout 300;
|
|
}
|
|
}
|
|
```
|
|
|
|
Enable it and reload nginx:
|
|
|
|
```bash
|
|
ln -s /etc/nginx/sites-available/rolemasterdb.franktovar.de /etc/nginx/sites-enabled/rolemasterdb.franktovar.de
|
|
nginx -t
|
|
systemctl reload nginx
|
|
```
|
|
|
|
At this point `http://rolemasterdb.franktovar.de` should work.
|
|
|
|
## HTTPS Setup
|
|
|
|
If `certbot` and the nginx plugin are installed, request the certificate:
|
|
|
|
```bash
|
|
certbot --nginx -d rolemasterdb.franktovar.de
|
|
```
|
|
|
|
That should update the nginx config to serve HTTPS and normally also install an HTTP-to-HTTPS redirect. Verify the generated config and then reload nginx if needed:
|
|
|
|
```bash
|
|
nginx -t
|
|
systemctl reload nginx
|
|
```
|
|
|
|
After that, `https://rolemasterdb.franktovar.de` should terminate TLS in nginx and proxy traffic to `127.0.0.1:8080`.
|
|
|
|
## Deploy
|
|
|
|
Run:
|
|
|
|
```bash
|
|
./scripts/deploy-vserver.sh
|
|
```
|
|
|
|
Or point at a different config file:
|
|
|
|
```bash
|
|
./scripts/deploy-vserver.sh /path/to/custom.env
|
|
```
|
|
|
|
## What The Script Does
|
|
|
|
1. Publishes `src/RolemasterDb.App/RolemasterDb.App.csproj` in `Release`.
|
|
2. Precreates `publish/wwwroot/components/layout` and `publish/wwwroot/components/shared` before publish.
|
|
This is required because the current project otherwise fails to publish two JavaScript static assets.
|
|
3. Replaces `publish/import-artifacts` with a full copy of `src/RolemasterDb.App/import-artifacts`.
|
|
This is required because the current publish output does not reliably include deep artifact folders such as `cells/` and `pages/`.
|
|
4. Bundles the publish output, `src/RolemasterDb.App/rolemaster.db`, and the runtime Dockerfile into `artifacts/deploy/<release-id>/`.
|
|
5. Uploads the bundle to the vserver.
|
|
6. Extracts the bundle on the vserver.
|
|
7. Seeds `REMOTE_DATA_DIR/rolemaster.db` on first deploy only.
|
|
8. Builds the Docker image on the vserver.
|
|
9. Recreates the container with:
|
|
|
|
```text
|
|
--restart unless-stopped
|
|
-p HOST_BIND_ADDRESS:HOST_PORT:CONTAINER_PORT
|
|
-v REMOTE_DATA_DIR:/app/data
|
|
ConnectionStrings__RolemasterDb=Data Source=/app/data/rolemaster.db
|
|
```
|
|
|
|
## Updating The App Later
|
|
|
|
Running the same deploy command again will:
|
|
|
|
- publish a fresh release bundle
|
|
- upload a new timestamped release
|
|
- keep the existing database in `REMOTE_DATA_DIR`
|
|
- keep the complete imported artifact tree inside the image for that release
|
|
- rebuild the image and restart the container
|
|
- leave the nginx config and TLS setup untouched
|
|
|
|
## Useful Remote Commands
|
|
|
|
Check the running container:
|
|
|
|
```bash
|
|
ssh myvserver docker ps
|
|
```
|
|
|
|
Follow logs:
|
|
|
|
```bash
|
|
ssh myvserver docker logs -f rolemasterdb
|
|
```
|
|
|
|
Check nginx:
|
|
|
|
```bash
|
|
ssh myvserver nginx -t
|
|
ssh myvserver systemctl status nginx
|
|
```
|