Back to Tutorials
Run Your First Docker Container
Learn how to run Nginx, Python, and Node.js containers from scratch using Zenithal.
Prerequisites
- Docker is installed and running (green status indicator in Zenithal sidebar)
- The image you want to use is available on Docker Hub or a connected registry
Scenario 1: Nginx Serving a Custom HTML Page
- Click Containers in the sidebar
- Click the + button (top-right) to open the Run Container sheet
- In the Image field, enter:
nginx:alpine - Set Container Name to:
my-nginx - Expand the Ports section and add a mapping:
- Host Port: 8080
- Container Port: 80
- Protocol: tcp
- Expand the Volumes section and add a bind mount:
- Host Path: click the folder icon and select a local folder (e.g.,
~/Projects/my-site) - Container Path:
/usr/share/nginx/html - Read Only: toggle ON (recommended for serving static files)
- Host Path: click the folder icon and select a local folder (e.g.,
- Click Run
Example File
Create ~/Projects/my-site/index.html before running the container:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello from Zenithal</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
}
.container {
text-align: center;
padding: 2rem;
}
h1 { font-size: 3rem; margin-bottom: 0.5rem; }
p { font-size: 1.2rem; opacity: 0.9; }
</style>
</head>
<body>
<div class="container">
<h1>Hello from Zenithal</h1>
<p>Served by Nginx inside a Docker container</p>
</div>
</body>
</html>Scenario 2: Python HTTP Server
- Open the Run Container sheet (Containers → +)
- Image:
python:3.12-slim - Container Name:
my-python - Command:
python3 /app/serve.py - Ports: 8000 → 8000 (tcp)
- Volumes: bind mount
~/Projects/my-python-app→/app(read-only OFF) - Click Run
Example File
Create ~/Projects/my-python-app/serve.py:
serve.py
from http.server import HTTPServer, SimpleHTTPRequestHandler
import os
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
html = """
<!DOCTYPE html>
<html>
<head><title>Python Server</title></head>
<body style="font-family: sans-serif; text-align: center; padding: 4rem;">
<h1>Hello from Python!</h1>
<p>Running inside Docker via Zenithal</p>
<p>Host: {host}</p>
</body>
</html>
""".format(host=os.environ.get("HOSTNAME", "unknown"))
self.wfile.write(html.encode())
if __name__ == "__main__":
server = HTTPServer(("0.0.0.0", 8000), MyHandler)
print("Server running on port 8000")
server.serve_forever()Scenario 3: Node.js Express App
- Open the Run Container sheet (Containers → +)
- Image:
node:20-alpine - Container Name:
my-node - Command:
sh -c "cd /app && npm install && node app.js" - Ports: 3000 → 3000 (tcp)
- Environment Variables:
NODE_ENV=development - Volumes: bind mount
~/Projects/my-node-app→/app - Click Run
Example Files
Create ~/Projects/my-node-app/package.json:
package.json
{
"name": "my-node-app",
"version": "1.0.0",
"main": "app.js",
"dependencies": {
"express": "^4.18.2"
}
}Create ~/Projects/my-node-app/app.js:
app.js
const express = require('express');
const app = express();
const PORT = 3000;
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head><title>Node.js App</title></head>
<body style="font-family: sans-serif; text-align: center; padding: 4rem;">
<h1>Hello from Node.js!</h1>
<p>Express ${require('express/package.json').version} running in Docker</p>
<p>Environment: ${process.env.NODE_ENV}</p>
</body>
</html>
`);
});
app.listen(PORT, '0.0.0.0', () => {
console.log(`Server running on port ${PORT}`);
});What You'll See
- The container appears in the Containers list with a green "Running" badge
- Clicking the container name opens the Inspect view with Overview, Env, Network, Mounts, and Resources tabs
- Open
http://localhost:8080(Nginx),http://localhost:8000(Python), orhttp://localhost:3000(Node) in your browser to see the page
Tips
- The Mount Path Suggestions feature shows common mount points for known images (e.g.,
/usr/share/nginx/htmlfor nginx) - Toggle Read Only on bind mounts when the container only needs to read files — this prevents accidental writes
- If a host port is already in use, Zenithal shows a port conflict warning — change the host port to resolve it
- You can set a Restart Policy (e.g.,
unless-stopped) in the Advanced section so the container auto-restarts after a Docker restart