app.py

Download
python 81 lines 1.9 KB
 1"""
 2Simple Flask application demonstrating containerization best practices.
 3
 4This application provides:
 5- A basic hello world endpoint
 6- A health check endpoint for container orchestration
 7- Proper logging and error handling
 8"""
 9
10from flask import Flask, jsonify
11import logging
12import os
13import signal
14import sys
15
16# Configure logging
17logging.basicConfig(
18    level=logging.INFO,
19    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
20)
21logger = logging.getLogger(__name__)
22
23app = Flask(__name__)
24
25
26@app.route('/')
27def hello():
28    """Main endpoint returning a simple greeting."""
29    logger.info("Hello endpoint accessed")
30    return jsonify({
31        'message': 'Hello from Docker!',
32        'version': '1.0',
33        'environment': os.getenv('ENVIRONMENT', 'development')
34    })
35
36
37@app.route('/health')
38def health():
39    """
40    Health check endpoint.
41
42    This is used by:
43    - Docker HEALTHCHECK directive
44    - Kubernetes liveness/readiness probes
45    - Load balancers
46
47    Returns:
48        JSON response with health status
49    """
50    return jsonify({
51        'status': 'healthy',
52        'service': 'flask-app'
53    }), 200
54
55
56def graceful_shutdown(signum, frame):
57    """
58    Handle graceful shutdown on SIGTERM.
59
60    This is important in container environments where the orchestrator
61    sends SIGTERM before forcefully killing the container.
62    """
63    logger.info(f"Received signal {signum}, shutting down gracefully...")
64    sys.exit(0)
65
66
67# Register signal handlers for graceful shutdown
68signal.signal(signal.SIGTERM, graceful_shutdown)
69signal.signal(signal.SIGINT, graceful_shutdown)
70
71
72if __name__ == '__main__':
73    # Get configuration from environment variables
74    port = int(os.getenv('PORT', 5000))
75    debug = os.getenv('DEBUG', 'False').lower() == 'true'
76
77    logger.info(f"Starting Flask application on port {port}")
78
79    # Use 0.0.0.0 to accept connections from outside the container
80    app.run(host='0.0.0.0', port=port, debug=debug)