Files
turmlibar-calendar/deploy-podman.sh
2025-10-30 14:55:37 +01:00

365 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Turmli Bar Calendar Tool - Podman Deployment Script
# Compatible with Podman and Podman-compose
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
IMAGE_NAME="turmli-calendar"
CONTAINER_NAME="turmli-calendar"
DEFAULT_PORT=8000
CACHE_FILE="calendar_cache.json"
# Print functions
print_error() {
echo -e "${RED}$1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
# Check for podman or docker
check_container_runtime() {
if command -v podman &> /dev/null; then
RUNTIME="podman"
print_success "Podman is installed"
elif command -v docker &> /dev/null; then
RUNTIME="docker"
print_warning "Podman not found, using Docker instead"
else
print_error "Neither Podman nor Docker is installed. Please install Podman or Docker first."
exit 1
fi
}
# Check for podman-compose or docker-compose
check_compose() {
if command -v podman-compose &> /dev/null; then
COMPOSE="podman-compose"
COMPOSE_FILE="podman-compose.yml"
print_success "podman-compose is installed"
elif command -v docker-compose &> /dev/null; then
COMPOSE="docker-compose"
COMPOSE_FILE="docker-compose.yml"
print_warning "podman-compose not found, using docker-compose instead"
else
print_warning "Compose tool not found. Will use standalone container commands."
COMPOSE=""
fi
}
build() {
print_info "Building container image..."
# Detect architecture
ARCH=$(uname -m)
print_info "Detected architecture: ${ARCH}"
# Choose appropriate Dockerfile based on architecture and availability
if [ -f "Dockerfile.minimal" ]; then
BUILD_FILE="Dockerfile.minimal"
print_info "Using minimal Dockerfile (no compilation required)"
elif [ "$ARCH" = "armv6l" ] || [ "$ARCH" = "armv7l" ] || [ "$ARCH" = "aarch64" ]; then
# ARM architecture (Raspberry Pi, etc.)
if [ -f "Dockerfile.arm" ]; then
BUILD_FILE="Dockerfile.arm"
print_info "Using ARM-optimized Dockerfile"
elif [ -f "Containerfile" ]; then
BUILD_FILE="Containerfile"
else
BUILD_FILE="Dockerfile"
fi
else
# x86_64 or other architectures
if [ -f "Containerfile" ]; then
BUILD_FILE="Containerfile"
else
BUILD_FILE="Dockerfile"
fi
fi
print_info "Using build file: ${BUILD_FILE}"
${RUNTIME} build -f ${BUILD_FILE} -t ${IMAGE_NAME} . || {
print_error "Failed to build container image"
print_info "Try using Dockerfile.minimal with simplified dependencies"
exit 1
}
print_success "Container image built successfully"
}
start() {
print_info "Starting calendar application..."
# Create cache file if it doesn't exist
if [ ! -f "${CACHE_FILE}" ]; then
echo "{}" > ${CACHE_FILE}
print_info "Created cache file: ${CACHE_FILE}"
fi
if [ -n "$COMPOSE" ] && [ -f "$COMPOSE_FILE" ]; then
# Use compose if available
print_info "Starting with ${COMPOSE}..."
${COMPOSE} -f ${COMPOSE_FILE} up -d || {
print_error "Failed to start application with compose"
exit 1
}
else
# Use standalone container command
print_info "Starting with ${RUNTIME}..."
# Check if container already exists
if ${RUNTIME} ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
print_info "Container already exists, removing it..."
${RUNTIME} rm -f ${CONTAINER_NAME}
fi
# Run container with Podman-specific options
${RUNTIME} run -d \
--name ${CONTAINER_NAME} \
-p ${PORT:-$DEFAULT_PORT}:8000 \
-e TZ=${TZ:-Europe/Berlin} \
-e PYTHONUNBUFFERED=1 \
-v $(pwd)/${CACHE_FILE}:/app/${CACHE_FILE}:Z \
--restart unless-stopped \
${IMAGE_NAME} || {
print_error "Failed to start container"
exit 1
}
fi
print_success "Application started successfully"
print_info "Access the calendar at: http://localhost:${PORT:-$DEFAULT_PORT}"
}
stop() {
print_info "Stopping calendar application..."
if [ -n "$COMPOSE" ] && [ -f "$COMPOSE_FILE" ]; then
${COMPOSE} -f ${COMPOSE_FILE} down || true
else
${RUNTIME} stop ${CONTAINER_NAME} 2>/dev/null || true
${RUNTIME} rm ${CONTAINER_NAME} 2>/dev/null || true
fi
print_success "Application stopped"
}
restart() {
stop
start
}
logs() {
if [ -n "$COMPOSE" ] && [ -f "$COMPOSE_FILE" ]; then
${COMPOSE} -f ${COMPOSE_FILE} logs -f
else
${RUNTIME} logs -f ${CONTAINER_NAME}
fi
}
status() {
echo -e "${BLUE}Container Status:${NC}"
if [ -n "$COMPOSE" ] && [ -f "$COMPOSE_FILE" ]; then
${COMPOSE} -f ${COMPOSE_FILE} ps
else
if ${RUNTIME} ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -q ${CONTAINER_NAME}; then
${RUNTIME} ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "NAMES|${CONTAINER_NAME}"
else
print_info "Container is not running"
return
fi
fi
echo ""
print_info "Testing application..."
if curl -s -f http://localhost:${PORT:-$DEFAULT_PORT}/api/events > /dev/null 2>&1; then
print_success "Application is healthy and responding"
else
print_error "Application is not responding"
fi
}
clean() {
print_info "Cleaning up..."
stop
# Remove image
${RUNTIME} rmi ${IMAGE_NAME} 2>/dev/null || true
# Clean up build cache (Podman specific)
if [ "$RUNTIME" = "podman" ]; then
${RUNTIME} system prune -f 2>/dev/null || true
fi
print_success "Cleanup complete"
}
# Generate systemd service for rootless Podman
generate_systemd() {
if [ "$RUNTIME" != "podman" ]; then
print_error "Systemd generation is only available for Podman"
exit 1
fi
print_info "Generating systemd service for rootless Podman..."
# Check if container is running
if ! ${RUNTIME} ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
print_error "Container must be running to generate systemd service"
print_info "Run './deploy-podman.sh start' first"
exit 1
fi
# Create user systemd directory if it doesn't exist
mkdir -p ~/.config/systemd/user/
# Generate systemd files
${RUNTIME} generate systemd --name --files --new ${CONTAINER_NAME}
# Move to user systemd directory
mv container-${CONTAINER_NAME}.service ~/.config/systemd/user/
print_success "Systemd service generated"
print_info "To enable the service:"
echo " systemctl --user daemon-reload"
echo " systemctl --user enable container-${CONTAINER_NAME}.service"
echo " systemctl --user start container-${CONTAINER_NAME}.service"
}
# Show help
show_help() {
echo "Turmli Bar Calendar - Podman Deployment Script"
echo ""
echo "Usage: $0 {build|start|stop|restart|logs|status|clean|systemd|info|help}"
echo ""
echo "Commands:"
echo " build - Build the container image"
echo " start - Build and start the application"
echo " stop - Stop the application"
echo " restart - Restart the application"
echo " logs - Show application logs"
echo " status - Check application status"
echo " clean - Remove containers and images"
echo " systemd - Generate systemd service (Podman only)"
echo " info - Show system and architecture information"
echo " help - Show this help message"
echo ""
echo "Environment Variables:"
echo " PORT - Port to expose (default: 8000)"
echo " TZ - Timezone (default: Europe/Berlin)"
echo ""
echo "Architecture Notes:"
echo " Dockerfile.minimal - Works on all architectures (no compilation)"
echo " Dockerfile.arm - ARM-optimized with simplified dependencies"
echo " Dockerfile - Standard multi-stage build (requires compilation)"
}
# Show system information
show_info() {
echo -e "${BLUE}System Information:${NC}"
echo " Architecture: $(uname -m)"
echo " OS: $(uname -s)"
echo " Kernel: $(uname -r)"
if command -v podman &> /dev/null; then
echo ""
echo -e "${BLUE}Podman Information:${NC}"
podman version --format " Version: {{.Client.Version}}"
podman info --format " Storage Driver: {{.Store.GraphDriverName}}"
podman info --format " Root: {{.Store.GraphRoot}}"
fi
if command -v docker &> /dev/null; then
echo ""
echo -e "${BLUE}Docker Information:${NC}"
docker version --format " Version: {{.Client.Version}}" 2>/dev/null || echo " Docker daemon not accessible"
fi
echo ""
echo -e "${BLUE}Build Configuration:${NC}"
ARCH=$(uname -m)
if [ -f "Dockerfile.minimal" ]; then
echo " Will use: Dockerfile.minimal (no compilation required)"
echo " Perfect for: All architectures including ARM/Raspberry Pi"
elif [ "$ARCH" = "armv6l" ] || [ "$ARCH" = "armv7l" ] || [ "$ARCH" = "aarch64" ]; then
echo " ARM architecture detected"
if [ -f "Dockerfile.arm" ]; then
echo " Will use: Dockerfile.arm (simplified dependencies)"
else
echo " Will use: Standard Dockerfile (may require longer build time)"
fi
else
echo " x86_64/standard architecture detected"
echo " Will use: Dockerfile or Containerfile"
fi
}
# Main script
case "$1" in
build)
check_container_runtime
build
;;
start)
check_container_runtime
check_compose
build
start
;;
stop)
check_container_runtime
check_compose
stop
;;
restart)
check_container_runtime
check_compose
restart
;;
logs)
check_container_runtime
check_compose
logs
;;
status)
check_container_runtime
check_compose
status
;;
clean)
check_container_runtime
clean
;;
systemd)
check_container_runtime
generate_systemd
;;
info)
show_info
;;
help)
show_help
;;
*)
show_help
exit 1
;;
esac