342 lines
9.5 KiB
Bash
342 lines
9.5 KiB
Bash
#!/bin/bash
|
|
|
|
# BCards Deploy Script - Containers Independentes
|
|
# Deploy automatizado da aplicação nos servidores OCI com Docker Compose
|
|
|
|
set -e
|
|
|
|
# Configurações
|
|
SERVER_IPS=("141.148.162.114" "129.146.116.218")
|
|
SSH_USER="ubuntu"
|
|
REGISTRY="registry.redecarneir.us"
|
|
APP_NAME="bcards-test-app"
|
|
CONTAINER_NAME="bcards-app"
|
|
NETWORK_NAME="bcards-network"
|
|
|
|
# Versão da aplicação (pode ser passada como parâmetro)
|
|
VERSION=${1:-"latest"}
|
|
|
|
# Cores para output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log() {
|
|
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}[ERROR] $1${NC}"
|
|
exit 1
|
|
}
|
|
|
|
warn() {
|
|
echo -e "${YELLOW}[WARNING] $1${NC}"
|
|
}
|
|
|
|
info() {
|
|
echo -e "${BLUE}[INFO] $1${NC}"
|
|
}
|
|
|
|
# Função para executar comando em servidor remoto
|
|
run_remote() {
|
|
local server_ip=$1
|
|
local command=$2
|
|
ssh -o StrictHostKeyChecking=no ${SSH_USER}@${server_ip} "$command"
|
|
}
|
|
|
|
|
|
# Verificar conectividade com servidores
|
|
check_connectivity() {
|
|
log "Verificando conectividade com os servidores..."
|
|
|
|
for server_ip in "${SERVER_IPS[@]}"; do
|
|
if ! ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no ${SSH_USER}@${server_ip} "echo 'ok'" >/dev/null 2>&1; then
|
|
error "Não foi possível conectar ao servidor $server_ip"
|
|
fi
|
|
info "✓ Servidor $server_ip conectado"
|
|
done
|
|
}
|
|
|
|
# Verificar se Docker está ativo
|
|
check_docker() {
|
|
log "Verificando status do Docker..."
|
|
|
|
for server_ip in "${SERVER_IPS[@]}"; do
|
|
if ! run_remote $server_ip "sudo docker info" >/dev/null 2>&1; then
|
|
error "Docker não está ativo no servidor $server_ip. Execute setup-servers.sh primeiro."
|
|
fi
|
|
info "✓ Docker está ativo no servidor $server_ip"
|
|
done
|
|
}
|
|
|
|
# Build da aplicação local (se necessário)
|
|
build_application() {
|
|
log "Building aplicação localmente..."
|
|
|
|
cd test-app
|
|
|
|
# Build da imagem Docker
|
|
info "Building imagem Docker..."
|
|
docker build -t ${APP_NAME}:${VERSION} .
|
|
|
|
# Tag para registry
|
|
docker tag ${APP_NAME}:${VERSION} ${REGISTRY}/${APP_NAME}:${VERSION}
|
|
docker tag ${APP_NAME}:${VERSION} ${REGISTRY}/${APP_NAME}:latest
|
|
|
|
info "✓ Aplicação construída com sucesso"
|
|
cd ..
|
|
}
|
|
|
|
# Push da imagem para registry
|
|
push_to_registry() {
|
|
log "Enviando imagem para registry..."
|
|
|
|
# Push da imagem
|
|
docker push ${REGISTRY}/${APP_NAME}:${VERSION}
|
|
docker push ${REGISTRY}/${APP_NAME}:latest
|
|
|
|
info "✓ Imagem enviada para registry"
|
|
}
|
|
|
|
# Deploy em containers independentes
|
|
deploy_containers() {
|
|
log "Fazendo deploy dos containers independentes..."
|
|
|
|
local server_count=1
|
|
|
|
for server_ip in "${SERVER_IPS[@]}"; do
|
|
info "Deploy no servidor $server_ip (Server $server_count)..."
|
|
|
|
# Criar docker-compose específico para cada servidor
|
|
cat > /tmp/docker-compose-server${server_count}.yml << EOF
|
|
version: '3.8'
|
|
|
|
services:
|
|
bcards-app:
|
|
image: ${REGISTRY}/${APP_NAME}:${VERSION}
|
|
container_name: ${CONTAINER_NAME}-server${server_count}
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8080:8080"
|
|
environment:
|
|
- ASPNETCORE_ENVIRONMENT=Production
|
|
- SERVER_NAME=BCards Server ${server_count}
|
|
- SERVER_COLOR=$([ $server_count -eq 1 ] && echo "#28a745" || echo "#007bff")
|
|
networks:
|
|
- bcards-network
|
|
mem_limit: 512m
|
|
mem_reservation: 256m
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
networks:
|
|
bcards-network:
|
|
external: true
|
|
EOF
|
|
|
|
# Copiar docker-compose para o servidor
|
|
scp /tmp/docker-compose-server${server_count}.yml ${SSH_USER}@${server_ip}:~/bcards/docker-compose.yml
|
|
|
|
# Pull da imagem
|
|
info "Fazendo pull da imagem no servidor $server_ip..."
|
|
run_remote $server_ip "sudo docker pull ${REGISTRY}/${APP_NAME}:${VERSION}"
|
|
|
|
# Parar container antigo se existir
|
|
run_remote $server_ip "sudo docker compose -f ~/bcards/docker-compose.yml down" || true
|
|
|
|
# Iniciar novo container
|
|
info "Iniciando container no servidor $server_ip..."
|
|
run_remote $server_ip "cd ~/bcards && sudo docker compose up -d"
|
|
|
|
((server_count++))
|
|
done
|
|
|
|
info "✓ Containers deployados com sucesso"
|
|
}
|
|
|
|
# Aguardar containers ficarem saudáveis
|
|
wait_for_health() {
|
|
log "Aguardando containers ficarem saudáveis..."
|
|
|
|
local max_attempts=30
|
|
local attempt=1
|
|
|
|
while [ $attempt -le $max_attempts ]; do
|
|
local healthy_containers=0
|
|
|
|
for server_ip in "${SERVER_IPS[@]}"; do
|
|
local container_health=$(run_remote $server_ip "sudo docker inspect --format='{{.State.Health.Status}}' ${CONTAINER_NAME}-server* 2>/dev/null" | grep -c "healthy" || echo "0")
|
|
((healthy_containers += container_health))
|
|
done
|
|
|
|
if [ "$healthy_containers" -eq "2" ]; then
|
|
info "✓ Todos os containers estão saudáveis"
|
|
return 0
|
|
fi
|
|
|
|
info "Tentativa $attempt/$max_attempts - Aguardando containers ficarem saudáveis... ($healthy_containers/2)"
|
|
sleep 10
|
|
((attempt++))
|
|
done
|
|
|
|
warn "Timeout aguardando containers ficarem saudáveis"
|
|
check_container_status
|
|
return 1
|
|
}
|
|
|
|
# Verificar saúde dos containers
|
|
check_container_status() {
|
|
log "Verificando saúde dos containers..."
|
|
|
|
local server_count=1
|
|
|
|
for server_ip in "${SERVER_IPS[@]}"; do
|
|
info "Status do servidor $server_ip:"
|
|
run_remote $server_ip "sudo docker ps --filter name=${CONTAINER_NAME}"
|
|
|
|
info "Health check do servidor $server_ip:"
|
|
run_remote $server_ip "sudo docker inspect --format='{{.State.Health.Status}}' ${CONTAINER_NAME}-server${server_count} 2>/dev/null" || true
|
|
|
|
info "Logs dos últimos 50 eventos do servidor $server_ip:"
|
|
run_remote $server_ip "sudo docker logs --tail 50 ${CONTAINER_NAME}-server${server_count}" || true
|
|
|
|
((server_count++))
|
|
done
|
|
}
|
|
|
|
# Teste de conectividade externa
|
|
test_connectivity() {
|
|
log "Testando conectividade externa..."
|
|
|
|
# Teste HTTP
|
|
if curl -f -s "http://bcards.site/health" >/dev/null 2>&1; then
|
|
info "✓ HTTP health check passou"
|
|
else
|
|
warn "HTTP health check falhou"
|
|
fi
|
|
|
|
# Teste HTTPS (se SSL estiver configurado)
|
|
if curl -f -s "https://bcards.site/health" >/dev/null 2>&1; then
|
|
info "✓ HTTPS health check passou"
|
|
else
|
|
warn "HTTPS health check falhou ou SSL não configurado"
|
|
fi
|
|
}
|
|
|
|
# Rollback em caso de falha
|
|
rollback() {
|
|
log "Executando rollback..."
|
|
|
|
for server_ip in "${SERVER_IPS[@]}"; do
|
|
info "Rollback no servidor $server_ip..."
|
|
|
|
# Parar container atual
|
|
run_remote $server_ip "sudo docker compose -f ~/bcards/docker-compose.yml down" || true
|
|
|
|
# Tentar usar imagem latest anterior
|
|
run_remote $server_ip "sudo docker pull ${REGISTRY}/${APP_NAME}:latest"
|
|
|
|
# Atualizar docker-compose para usar latest
|
|
run_remote $server_ip "sed -i 's/:${VERSION}/:latest/g' ~/bcards/docker-compose.yml"
|
|
|
|
# Reiniciar com versão anterior
|
|
run_remote $server_ip "cd ~/bcards && sudo docker compose up -d"
|
|
done
|
|
|
|
info "Rollback executado"
|
|
}
|
|
|
|
# Limpeza de imagens antigas
|
|
cleanup_old_images() {
|
|
log "Limpando imagens antigas..."
|
|
|
|
for server_ip in "${SERVER_IPS[@]}"; do
|
|
info "Limpando imagens no servidor $server_ip..."
|
|
run_remote $server_ip "
|
|
sudo docker image prune -f
|
|
sudo docker container prune -f
|
|
"
|
|
done
|
|
|
|
info "✓ Limpeza concluída"
|
|
}
|
|
|
|
# Função principal
|
|
main() {
|
|
log "Iniciando deploy para versão $VERSION..."
|
|
|
|
# Verificações pré-deploy
|
|
check_connectivity
|
|
check_docker
|
|
|
|
# Build e push
|
|
if [[ "$2" != "--skip-build" ]]; then
|
|
build_application
|
|
push_to_registry
|
|
else
|
|
info "Pulando build (--skip-build especificado)"
|
|
fi
|
|
|
|
# Deploy
|
|
deploy_containers
|
|
|
|
# Verificações pós-deploy
|
|
if wait_for_health; then
|
|
check_container_status
|
|
test_connectivity
|
|
cleanup_old_images
|
|
|
|
log "Deploy concluído com sucesso!"
|
|
info "Aplicação disponível em: http://bcards.site"
|
|
info "Health check: http://bcards.site/health"
|
|
else
|
|
error "Deploy falhou - serviços não ficaram saudáveis"
|
|
if [[ "$3" == "--auto-rollback" ]]; then
|
|
rollback
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Mostrar help
|
|
show_help() {
|
|
echo "BCards Deploy Script"
|
|
echo ""
|
|
echo "Usage: $0 [VERSION] [OPTIONS]"
|
|
echo ""
|
|
echo "VERSION:"
|
|
echo " Versão da aplicação para deploy (default: latest)"
|
|
echo ""
|
|
echo "OPTIONS:"
|
|
echo " --skip-build Pula o build local da aplicação"
|
|
echo " --auto-rollback Executa rollback automático em caso de falha"
|
|
echo " --help Mostra esta ajuda"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 # Deploy versão latest"
|
|
echo " $0 v1.2.3 # Deploy versão específica"
|
|
echo " $0 latest --skip-build # Deploy sem rebuild"
|
|
echo ""
|
|
echo "Servers: ${SERVER_IPS[*]}"
|
|
echo "Registry: $REGISTRY"
|
|
}
|
|
|
|
# Parse argumentos
|
|
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
|
show_help
|
|
exit 0
|
|
fi
|
|
|
|
# Executar função principal
|
|
main "$@" |