Skip to content

Commit 9248aa9

Browse files
authored
Merge pull request #83 from edgeengineer/jo/run-dockerfile
Add the ability to run Dockerfile based containers (non-Swift!)
2 parents 3bb3412 + a96dd37 commit 9248aa9

File tree

13 files changed

+535
-78
lines changed

13 files changed

+535
-78
lines changed

Examples/HelloPython/.dockerignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Git
2+
.git
3+
.gitignore
4+
5+
# Documentation
6+
README.md
7+
*.md
8+
9+
# Python
10+
__pycache__/
11+
*.py[cod]
12+
*$py.class
13+
*.so
14+
.Python
15+
env/
16+
venv/
17+
ENV/
18+
env.bak/
19+
venv.bak/
20+
21+
# IDE
22+
.vscode/
23+
.idea/
24+
*.swp
25+
*.swo
26+
27+
# OS
28+
.DS_Store
29+
Thumbs.db

Examples/HelloPython/Dockerfile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Use Python 3.11 slim image as base
2+
FROM python:3.11-slim
3+
4+
# Set working directory
5+
WORKDIR /app
6+
7+
# Copy requirements first for better caching
8+
COPY requirements.txt .
9+
10+
# Install dependencies (none in this case, but good practice)
11+
RUN pip install --no-cache-dir -r requirements.txt
12+
13+
# Copy application code
14+
COPY app.py .
15+
16+
# Create a non-root user for security
17+
RUN useradd --create-home --shell /bin/bash app && \
18+
chown -R app:app /app
19+
USER app
20+
21+
# Expose port 8080
22+
EXPOSE 8080
23+
24+
# Set environment variable for port
25+
ENV PORT=8080
26+
27+
# Health check
28+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
29+
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"
30+
31+
# Run the application
32+
CMD ["python", "app.py"]

Examples/HelloPython/README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Hello World Python HTTP Server
2+
3+
A simple Python HTTP server with Docker support for easy deployment.
4+
5+
## Features
6+
7+
- Simple HTTP server using Python's built-in `http.server` module
8+
- Multiple endpoints:
9+
- `GET /` - HTML Hello World page
10+
- `GET /api/hello` - JSON API response
11+
- `GET /health` - Health check endpoint
12+
- `POST /api/echo` - Echo back posted data
13+
- Dockerized for easy deployment
14+
- Health check included
15+
- Non-root user for security
16+
17+
## Quick Start
18+
19+
### Run Locally
20+
21+
```bash
22+
# Run the server directly
23+
python app.py
24+
25+
# Or with custom port
26+
PORT=3000 python app.py
27+
```
28+
29+
Visit `http://localhost:8000` to see the Hello World page.
30+
31+
### Run with Docker
32+
33+
```bash
34+
# Build the Docker image
35+
docker build -t hello-python-server .
36+
37+
# Run the container
38+
docker run -p 8000:8000 hello-python-server
39+
40+
# Or run in background
41+
docker run -d -p 8000:8000 --name hello-server hello-python-server
42+
```
43+
44+
### Test the Endpoints
45+
46+
```bash
47+
# HTML page
48+
curl http://localhost:8000/
49+
50+
# JSON API
51+
curl http://localhost:8000/api/hello
52+
53+
# Health check
54+
curl http://localhost:8000/health
55+
56+
# Echo endpoint
57+
curl -X POST http://localhost:8000/api/echo -d "Hello from curl"
58+
```
59+
60+
## Deployment Options
61+
62+
### Docker Hub
63+
64+
```bash
65+
# Tag for Docker Hub
66+
docker tag hello-python-server yourusername/hello-python-server
67+
68+
# Push to Docker Hub
69+
docker push yourusername/hello-python-server
70+
71+
# Run from Docker Hub
72+
docker run -p 8000:8000 yourusername/hello-python-server
73+
```
74+
75+
### Cloud Platforms
76+
77+
This containerized application can be deployed to:
78+
- AWS ECS/Fargate
79+
- Google Cloud Run
80+
- Azure Container Instances
81+
- Kubernetes
82+
- Heroku (with container stack)
83+
- DigitalOcean App Platform
84+
85+
### Environment Variables
86+
87+
- `PORT`: Server port (default: 8000)
88+
89+
## File Structure
90+
91+
```
92+
.
93+
├── app.py # Main Python server
94+
├── requirements.txt # Python dependencies (none required)
95+
├── Dockerfile # Docker configuration
96+
├── .dockerignore # Docker ignore file
97+
└── README.md # This file
98+
```
99+
100+
## Development
101+
102+
The server uses Python's built-in HTTP server, so no external dependencies are required. The code is simple and easy to modify for your needs.
103+
104+
## Security Notes
105+
106+
- The Docker container runs as a non-root user
107+
- Only necessary files are copied to the container
108+
- Health checks are included for monitoring

Examples/HelloPython/app.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Simple Hello World Python HTTP Server
4+
"""
5+
6+
from http.server import HTTPServer, BaseHTTPRequestHandler
7+
import json
8+
import os
9+
10+
class HelloWorldHandler(BaseHTTPRequestHandler):
11+
def do_GET(self):
12+
if self.path == '/':
13+
self.send_response(200)
14+
self.send_header('Content-type', 'text/html')
15+
self.end_headers()
16+
17+
html_content = """
18+
<!DOCTYPE html charset="utf-8">
19+
<html lang="en">
20+
<head>
21+
<title>Hello World Server</title>
22+
<style>
23+
body {
24+
font-family: Arial, sans-serif;
25+
max-width: 800px;
26+
margin: 50px auto;
27+
padding: 20px;
28+
background-color: #f5f5f5;
29+
}
30+
.container {
31+
background-color: white;
32+
padding: 30px;
33+
border-radius: 10px;
34+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
35+
text-align: center;
36+
}
37+
h1 { color: #333; }
38+
.status { color: #28a745; font-weight: bold; }
39+
</style>
40+
</head>
41+
<body>
42+
<div class="container">
43+
<h1>Hello World! 🌍</h1>
44+
<p class="status">Server is running successfully!</p>
45+
<p>This is a simple Python HTTP server running in a Docker container.</p>
46+
</div>
47+
</body>
48+
</html>
49+
"""
50+
self.wfile.write(html_content.encode())
51+
52+
elif self.path == '/api/hello':
53+
self.send_response(200)
54+
self.send_header('Content-type', 'application/json')
55+
self.end_headers()
56+
57+
response = {
58+
"message": "Hello World!",
59+
"status": "success",
60+
"server": "Python HTTP Server"
61+
}
62+
self.wfile.write(json.dumps(response, indent=2).encode())
63+
64+
elif self.path == '/health':
65+
self.send_response(200)
66+
self.send_header('Content-type', 'application/json')
67+
self.end_headers()
68+
69+
health_response = {
70+
"status": "healthy",
71+
"message": "Server is running"
72+
}
73+
self.wfile.write(json.dumps(health_response).encode())
74+
75+
else:
76+
self.send_response(404)
77+
self.send_header('Content-type', 'application/json')
78+
self.end_headers()
79+
80+
error_response = {
81+
"error": "Not Found",
82+
"message": f"Path {self.path} not found"
83+
}
84+
self.wfile.write(json.dumps(error_response).encode())
85+
86+
def do_POST(self):
87+
if self.path == '/api/echo':
88+
content_length = int(self.headers['Content-Length'])
89+
post_data = self.rfile.read(content_length)
90+
91+
self.send_response(200)
92+
self.send_header('Content-type', 'application/json')
93+
self.end_headers()
94+
95+
response = {
96+
"message": "Echo endpoint",
97+
"received_data": post_data.decode('utf-8'),
98+
"status": "success"
99+
}
100+
self.wfile.write(json.dumps(response, indent=2).encode())
101+
else:
102+
self.send_response(404)
103+
self.send_header('Content-type', 'application/json')
104+
self.end_headers()
105+
106+
error_response = {
107+
"error": "Not Found",
108+
"message": f"POST endpoint {self.path} not found"
109+
}
110+
self.wfile.write(json.dumps(error_response).encode())
111+
112+
def log_message(self, format, *args):
113+
print(f"[{self.date_time_string()}] {format % args}")
114+
115+
def run_server(port=8000):
116+
server_address = ('', port)
117+
httpd = HTTPServer(server_address, HelloWorldHandler)
118+
print(f"Server running on port {port}")
119+
print(f"Visit http://localhost:{port} to see the Hello World page")
120+
print(f"API endpoints available:")
121+
print(f" GET /api/hello - JSON hello message")
122+
print(f" GET /health - Health check")
123+
print(f" POST /api/echo - Echo back posted data")
124+
125+
try:
126+
httpd.serve_forever()
127+
except KeyboardInterrupt:
128+
print("\nShutting down server...")
129+
httpd.shutdown()
130+
131+
if __name__ == '__main__':
132+
port = int(os.environ.get('PORT', 8000))
133+
run_server(port)

Examples/HelloPython/edge.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"appId": "engineer.edge.examples.hellopython",
3+
"version": "1.0.0",
4+
"entitlements": [
5+
{
6+
"type": "network",
7+
"mode": "host"
8+
}
9+
]
10+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# No external dependencies required for this simple server
2+
# Using only Python standard library modules

0 commit comments

Comments
 (0)