Deploy Your First App
Deploy a simple web application to Gordon in under 10 minutes.
What You'll Learn
- Building a container image
- Pushing to Gordon's registry
- Configuring routes
- Deploying your app
Prerequisites
- Gordon running on your VPS
- Docker installed locally
- Domain configured (e.g.,
app.mydomain.com)
Steps
1. Create a Simple App
Create a new directory with a simple Node.js app:
mkdir my-first-app
cd my-first-app
Create server.js:
const http = require('http');
const port = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<html>
<body>
<h1>Hello from Gordon!</h1>
<p>Deployed at: ${new Date().toISOString()}</p>
</body>
</html>
`);
});
server.listen(port, '0.0.0.0', () => {
console.log(`Server running on port ${port}`);
});
Create Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY server.js .
ENV PORT=3000
EXPOSE 3000
CMD ["node", "server.js"]
2. Build the Image
docker build -t my-first-app .
3. Tag for Gordon Registry
Replace registry.mydomain.com with your Gordon registry domain:
docker tag my-first-app registry.mydomain.com/my-first-app:latest
On your Gordon server, edit ~/.config/gordon/gordon.toml:
[routes]
"app.mydomain.com" = "my-first-app:latest"
Reload Gordon:
gordon daemon reload
5. Push to Deploy
Login to your registry (if auth enabled):
docker login registry.mydomain.com
Push the image:
docker push registry.mydomain.com/my-first-app:latest
6. Verify Deployment
Visit https://app.mydomain.com in your browser.
You should see "Hello from Gordon!" with the deployment timestamp.
Common Issues
"unauthorized" on push
Enable registry authentication or check credentials:
gordon auth token generate --subject deploy --expiry 0
docker login -u deploy -p <token> registry.mydomain.com
App not accessible
-
Check the container is running:
docker ps | grep my-first-app
-
Check Gordon logs:
gordon daemon logs -f
-
Ensure DNS points to your server
Wrong port
If your app uses a different port, expose it in Dockerfile:
ENV PORT=8080
EXPOSE 8080
Updating Your App
Make changes, then rebuild and push:
# Edit server.js
docker build -t my-first-app .
docker tag my-first-app registry.mydomain.com/my-first-app:latest
docker push registry.mydomain.com/my-first-app:latest
Gordon replaces the running container: it withdraws traffic, stops and removes the old container, starts the new one, waits for it to pass its readiness probe, and routes traffic to it. Expect a short interruption at that point.
Next Steps
source
1# Deploy Your First App
2
3Deploy a simple web application to Gordon in under 10 minutes.
4
5## What You'll Learn
6
7- Building a container image
8- Pushing to Gordon's registry
9- Configuring routes
10- Deploying your app
11
12## Prerequisites
13
14- Gordon running on your VPS
15- Docker installed locally
16- Domain configured (e.g., `app.mydomain.com`)
17
18## Steps
19
20### 1. Create a Simple App
21
22Create a new directory with a simple Node.js app:
23
24```bash
25mkdir my-first-app
26cd my-first-app
27```
28
29Create `server.js`:
30
31```javascript
32const http = require('http');
33
34const port = process.env.PORT || 3000;
35
36const server = http.createServer((req, res) => {
37 res.writeHead(200, { 'Content-Type': 'text/html' });
38 res.end(`
39 <html>
40 <body>
41 <h1>Hello from Gordon!</h1>
42 <p>Deployed at: ${new Date().toISOString()}</p>
43 </body>
44 </html>
45 `);
46});
47
48server.listen(port, '0.0.0.0', () => {
49 console.log(`Server running on port ${port}`);
50});
51```
52
53Create `Dockerfile`:
54
55```dockerfile
56FROM node:18-alpine
57WORKDIR /app
58COPY server.js .
59ENV PORT=3000
60EXPOSE 3000
61CMD ["node", "server.js"]
62```
63
64### 2. Build the Image
65
66```bash
67docker build -t my-first-app .
68```
69
70### 3. Tag for Gordon Registry
71
72Replace `registry.mydomain.com` with your Gordon registry domain:
73
74```bash
75docker tag my-first-app registry.mydomain.com/my-first-app:latest
76```
77
78### 4. Configure the Route
79
80On your Gordon server, edit `~/.config/gordon/gordon.toml`:
81
82```toml
83[routes]
84"app.mydomain.com" = "my-first-app:latest"
85```
86
87Reload Gordon:
88
89```bash
90gordon daemon reload
91```
92
93### 5. Push to Deploy
94
95Login to your registry (if auth enabled):
96
97```bash
98docker login registry.mydomain.com
99```
100
101Push the image:
102
103```bash
104docker push registry.mydomain.com/my-first-app:latest
105```
106
107### 6. Verify Deployment
108
109Visit `https://app.mydomain.com` in your browser.
110
111You should see "Hello from Gordon!" with the deployment timestamp.
112
113## Common Issues
114
115### "unauthorized" on push
116
117Enable registry authentication or check credentials:
118
119```bash
120gordon auth token generate --subject deploy --expiry 0
121docker login -u deploy -p <token> registry.mydomain.com
122```
123
124### App not accessible
125
1261. Check the container is running:
127 ```bash
128 docker ps | grep my-first-app
129 ```
130
1312. Check Gordon logs:
132 ```bash
133 gordon daemon logs -f
134 ```
135
1363. Ensure DNS points to your server
137
138### Wrong port
139
140If your app uses a different port, expose it in Dockerfile:
141
142```dockerfile
143ENV PORT=8080
144EXPOSE 8080
145```
146
147## Updating Your App
148
149Make changes, then rebuild and push:
150
151```bash
152# Edit server.js
153docker build -t my-first-app .
154docker tag my-first-app registry.mydomain.com/my-first-app:latest
155docker push registry.mydomain.com/my-first-app:latest
156```
157
158Gordon replaces the running container: it withdraws traffic, stops and removes the old container, starts the new one, waits for it to pass its readiness probe, and routes traffic to it. Expect a short interruption at that point.
159
160## Next Steps
161
162- [Add environment variables](/docs/config/apps.md)
163- [Add a database](./postgres-service.md)
164- [Set up CI/CD](/docs/deployment/github-actions.md)