Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions 1-5-running-docker-compose/app-python/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
# Use an official Python runtime as a parent image
FROM python:2.7-slim
FROM python:3.11-slim

# Set the working directory to /app
WORKDIR /app

# Create a non-root user to run the application
RUN groupadd -r appuser && useradd -r -g appuser appuser

# Copy the app code and dependencies file into the container at /app
ADD . /app
# Use COPY instead of ADD for better transparency (security best practice)
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt

COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
# Change ownership of the app directory to the non-root user
RUN chown -R appuser:appuser /app

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World
ENV NAME=World

# Switch to non-root user
USER appuser

# Run app.py when the container launches
CMD ["python", "app.py"]
80 changes: 71 additions & 9 deletions 1-5-running-docker-compose/app-python/app.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,85 @@
from flask import Flask, render_template
from redis import Redis, RedisError
"""
Flask application with Redis counter.

This application demonstrates a simple Flask web server that maintains
a visitor counter using Redis as a backend store.
"""
import logging
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
from flask import Flask, render_template
from redis import Redis, RedisError

# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# Configuration from environment variables
REDIS_HOST = os.getenv("REDIS_HOST", "redis")
REDIS_DB = int(os.getenv("REDIS_DB", "0"))
REDIS_TIMEOUT = int(os.getenv("REDIS_TIMEOUT", "2"))
FLASK_HOST = os.getenv("FLASK_HOST", "0.0.0.0")
FLASK_PORT = int(os.getenv("FLASK_PORT", "80"))
FLASK_DEBUG = os.getenv("FLASK_DEBUG", "False").lower() == "true"

# Connect to Redis with proper error handling
try:
redis = Redis(
host=REDIS_HOST,
db=REDIS_DB,
socket_connect_timeout=REDIS_TIMEOUT,
socket_timeout=REDIS_TIMEOUT
)
# Test connection
redis.ping()
logger.info("Successfully connected to Redis at %s", REDIS_HOST)
except (RedisError, ConnectionError) as e:
logger.warning("Failed to connect to Redis: %s. Counter will be disabled.", str(e))
redis = None

app = Flask(__name__)


@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
"""
Main route handler that displays a greeting page with visit counter.

Returns:
str: Rendered HTML template with greeting message, hostname, and visit count
"""
visits = None

if redis is not None:
try:
visits = redis.incr("counter")
logger.debug("Visit counter incremented to: %s", visits)
except RedisError as e:
logger.error("Redis error while incrementing counter: %s", str(e))
visits = "cannot connect to Redis, counter disabled"
else:
visits = "cannot connect to Redis, counter disabled"

name = os.getenv("NAME", "world")
hostname = socket.gethostname()
return render_template('hello.html', name=name, hostname=hostname, visits=visits)

return render_template(
'hello.html',
name=name,
hostname=hostname,
visits=visits
)


if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
logger.info(
"Starting Flask application on %s:%d (debug=%s)",
FLASK_HOST,
FLASK_PORT,
FLASK_DEBUG
)
app.run(host=FLASK_HOST, port=FLASK_PORT, debug=FLASK_DEBUG)
4 changes: 2 additions & 2 deletions 1-5-running-docker-compose/app-python/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Flask
Redis
Flask>=3.0.0
redis>=5.0.0
20 changes: 15 additions & 5 deletions 2-building-images/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
# Use an official Python runtime as a parent image
FROM python:2.7-slim
FROM python:3.11-slim

# Set the working directory to /app
WORKDIR /app

# Create a non-root user to run the application
RUN groupadd -r appuser && useradd -r -g appuser appuser

# Copy the app code and dependencies file into the container at /app
ADD . /app
# Use COPY instead of ADD for better transparency (security best practice)
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt

COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
# Change ownership of the app directory to the non-root user
RUN chown -R appuser:appuser /app

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World
ENV NAME=World

# Switch to non-root user
USER appuser

# Run app.py when the container launches
CMD ["python", "app.py"]
80 changes: 71 additions & 9 deletions 2-building-images/app.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,85 @@
from flask import Flask, render_template
from redis import Redis, RedisError
"""
Flask application with Redis counter.

This application demonstrates a simple Flask web server that maintains
a visitor counter using Redis as a backend store.
"""
import logging
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
from flask import Flask, render_template
from redis import Redis, RedisError

# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# Configuration from environment variables
REDIS_HOST = os.getenv("REDIS_HOST", "redis")
REDIS_DB = int(os.getenv("REDIS_DB", "0"))
REDIS_TIMEOUT = int(os.getenv("REDIS_TIMEOUT", "2"))
FLASK_HOST = os.getenv("FLASK_HOST", "0.0.0.0")
FLASK_PORT = int(os.getenv("FLASK_PORT", "80"))
FLASK_DEBUG = os.getenv("FLASK_DEBUG", "False").lower() == "true"

# Connect to Redis with proper error handling
try:
redis = Redis(
host=REDIS_HOST,
db=REDIS_DB,
socket_connect_timeout=REDIS_TIMEOUT,
socket_timeout=REDIS_TIMEOUT
)
# Test connection
redis.ping()
logger.info("Successfully connected to Redis at %s", REDIS_HOST)
except (RedisError, ConnectionError) as e:
logger.warning("Failed to connect to Redis: %s. Counter will be disabled.", str(e))
redis = None

app = Flask(__name__)


@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
"""
Main route handler that displays a greeting page with visit counter.

Returns:
str: Rendered HTML template with greeting message, hostname, and visit count
"""
visits = None

if redis is not None:
try:
visits = redis.incr("counter")
logger.debug("Visit counter incremented to: %s", visits)
except RedisError as e:
logger.error("Redis error while incrementing counter: %s", str(e))
visits = "cannot connect to Redis, counter disabled"
else:
visits = "cannot connect to Redis, counter disabled"

name = os.getenv("NAME", "world")
hostname = socket.gethostname()
return render_template('hello.html', name=name, hostname=hostname, visits=visits)

return render_template(
'hello.html',
name=name,
hostname=hostname,
visits=visits
)


if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
logger.info(
"Starting Flask application on %s:%d (debug=%s)",
FLASK_HOST,
FLASK_PORT,
FLASK_DEBUG
)
app.run(host=FLASK_HOST, port=FLASK_PORT, debug=FLASK_DEBUG)
4 changes: 2 additions & 2 deletions 2-building-images/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Flask
Redis
Flask>=3.0.0
redis>=5.0.0