Files
michaelschiemer/deploy-direct.sh
Michael Schiemer 9526034e18 Simplify Docker Compose to single-file architecture
- Convert multi-file overlay approach to single docker-compose.yml
- Use environment variables for dev/production differences
- Remove complex network configuration conflicts
- Align with framework principles: simplicity over complexity
- Production config via .env.production file

Benefits:
- No more network subnet conflicts
- Single source of truth
- Framework-compliant architecture
- Easier maintenance and debugging

Related: #19 Docker network conflict resolution
2025-09-12 23:36:05 +02:00

176 lines
5.1 KiB
Bash
Executable File

#!/bin/bash
# Direct Docker-based production deployment
# Bypasses Ansible for immediate deployment
set -euo pipefail
SERVER_USER="deploy"
SERVER_IP="94.16.110.151"
REMOTE_PATH="/home/deploy/michaelschiemer"
SSH_OPTS="-o StrictHostKeyChecking=no"
# Colors for output
GREEN="\e[32m"
YELLOW="\e[33m"
RED="\e[31m"
RESET="\e[0m"
log_info() {
echo -e "${YELLOW}[INFO]${RESET} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${RESET} $1"
}
log_error() {
echo -e "${RED}[ERROR]${RESET} $1"
}
# Check prerequisites
check_prerequisites() {
log_info "Checking prerequisites..."
if ! ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "echo 'SSH connection successful'" 2>/dev/null; then
log_error "Cannot connect to production server. Please configure SSH key authentication."
log_error "Run: ssh-copy-id -i ~/.ssh/production $SERVER_USER@$SERVER_IP"
exit 1
fi
if ! command -v docker &> /dev/null; then
log_error "Docker not found locally. Install Docker first."
exit 1
fi
log_success "Prerequisites check passed"
}
# Build and push production image
build_and_push() {
local image_tag="$(git rev-parse --short HEAD)"
log_info "Building production image with tag: $image_tag"
# Build production image
docker build -t "michaelschiemer/php-framework:$image_tag" \
-f docker/php/Dockerfile \
--target=production \
--build-arg ENV=production \
.
# Tag as latest for production
docker tag "michaelschiemer/php-framework:$image_tag" \
"michaelschiemer/php-framework:production"
log_success "Production image built successfully"
echo "$image_tag"
}
# Deploy to production server
deploy_to_server() {
local image_tag="$1"
log_info "Deploying to production server..."
# Create deployment directory
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "mkdir -p $REMOTE_PATH"
# Copy docker-compose files
scp $SSH_OPTS docker-compose.yml "$SERVER_USER@$SERVER_IP:$REMOTE_PATH/"
scp $SSH_OPTS deployment/applications/docker-compose.production.yml "$SERVER_USER@$SERVER_IP:$REMOTE_PATH/"
# Copy environment file template
scp $SSH_OPTS .env.production "$SERVER_USER@$SERVER_IP:$REMOTE_PATH/.env" 2>/dev/null || {
log_info "Creating production environment file..."
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "cat > $REMOTE_PATH/.env << 'EOF'
APP_ENV=production
APP_DEBUG=false
DB_HOST=db
DB_DATABASE=framework
DB_USERNAME=framework
DB_PASSWORD=secure_password_change_me
REDIS_HOST=redis
REDIS_PORT=6379
EOF"
}
# Save Docker image and transfer
log_info "Transferring Docker image..."
docker save "michaelschiemer/php-framework:$image_tag" | \
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "docker load"
# Deploy with Docker Compose
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
cd $REMOTE_PATH
# Stop existing services
docker compose -f docker-compose.yml -f docker-compose.production.yml down --remove-orphans || true
# Start services with production configuration
IMAGE_TAG=$image_tag docker compose -f docker-compose.yml -f docker-compose.production.yml up -d
# Wait for services to be healthy
sleep 30
# Run health check
if docker compose -f docker-compose.yml -f docker-compose.production.yml ps | grep -q 'healthy\\|Up'; then
echo 'Deployment successful!'
else
echo 'Health check failed!'
docker compose -f docker-compose.yml -f docker-compose.production.yml logs --tail=50
exit 1
fi
"
log_success "Deployment completed successfully!"
}
# Validate deployment
validate_deployment() {
log_info "Validating production deployment..."
# Test HTTPS endpoint
if curl -f -k -H "User-Agent: Mozilla/5.0" "https://$SERVER_IP/health" >/dev/null 2>&1; then
log_success "HTTPS health check passed"
else
log_error "HTTPS health check failed"
return 1
fi
# Check that debug routes are blocked
local debug_response=$(curl -s -o /dev/null -w '%{http_code}' -k -H "User-Agent: Mozilla/5.0" "https://$SERVER_IP/debug" 2>/dev/null || echo 'connection_failed')
if [ "$debug_response" = '404' ]; then
log_success "Debug routes properly blocked"
else
log_error "WARNING: Debug routes not properly blocked (got: $debug_response)"
fi
log_success "Deployment validation completed"
}
# Main execution
main() {
log_info "Starting direct production deployment..."
# Check prerequisites
check_prerequisites
# Build and get image tag
local image_tag
image_tag=$(build_and_push)
# Deploy to server
deploy_to_server "$image_tag"
# Validate deployment
validate_deployment
log_success "Production deployment completed successfully!"
log_info "Application available at: https://michaelschiemer.de"
log_info "Deployed commit: $(git rev-parse HEAD)"
}
# Execute if run directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi