├── projeto-devops-fase-2 ├── provider.tf ├── ecr.tf ├── backend.tf └── ec2.tf ├── projeto-devops-fase-1 ├── referencia │ ├── docker-compose.yml │ ├── Dockerfile │ └── .dockerignore ├── website │ ├── js │ │ └── script.js │ ├── index.html │ └── css │ │ └── style.css └── README.md ├── .gitignore ├── LICENSE ├── projeto-devops-fase-3 └── .github │ └── workflows │ └── terraform.yaml ├── projeto-devops-fase-4 ├── repositorio-aplicacao │ └── .github │ │ └── workflows │ │ ├── deploy.yaml │ │ └── deploy2.yaml └── README.md └── README.md /projeto-devops-fase-2/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-2" 3 | 4 | } 5 | -------------------------------------------------------------------------------- /projeto-devops-fase-2/ecr.tf: -------------------------------------------------------------------------------- 1 | #ECR Repository 2 | resource "aws_ecr_repository" "ecr_site" { 3 | name = "site_prod" 4 | image_tag_mutability = "MUTABLE" 5 | } -------------------------------------------------------------------------------- /projeto-devops-fase-2/backend.tf: -------------------------------------------------------------------------------- 1 | # state.tf 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-marialazara" 5 | key = "site/terraform.tfstate" 6 | region = "us-east-2" 7 | encrypt = true 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projeto-devops-fase-1/referencia/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '1.0' 2 | 3 | services: 4 | web: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | ports: 9 | - "80:80" 10 | volumes: 11 | - ./website:/usr/share/nginx/html 12 | networks: 13 | - webnet 14 | 15 | networks: 16 | webnet: -------------------------------------------------------------------------------- /projeto-devops-fase-1/referencia/Dockerfile: -------------------------------------------------------------------------------- 1 | # Imagem base - Nginx Alpine (leve e eficiente) 2 | FROM nginx:alpine 3 | 4 | # Copia os arquivos do website para o diretório do Nginx 5 | COPY website/ /usr/share/nginx/html/ 6 | 7 | # Expõe a porta 80 (documentação - não abre a porta realmente) 8 | EXPOSE 80 9 | 10 | # Comando padrão quando o container iniciar 11 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /projeto-devops-fase-1/referencia/.dockerignore: -------------------------------------------------------------------------------- 1 | # Arquivos de documentação 2 | README.md 3 | docs/ 4 | *.md 5 | 6 | # Arquivos de configuração do projeto 7 | .git 8 | .gitignore 9 | Dockerfile 10 | docker-compose.yml 11 | 12 | # Logs 13 | *.log 14 | logs/ 15 | 16 | # Arquivos temporários 17 | *.tmp 18 | *.temp 19 | .DS_Store 20 | Thumbs.db 21 | 22 | 23 | # Arquivos de IDE 24 | .vscode/ 25 | .idea/ 26 | *.swp 27 | *.swo 28 | 29 | # Arquivos de backup 30 | *.backup 31 | *.bak -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Terraform files 2 | *.tfstate 3 | *.tfstate.* 4 | *.tfvars 5 | .terraform/ 6 | .terraform.lock.hcl 7 | *.tfplan 8 | 9 | # Local .terraform directories 10 | **/.terraform/* 11 | 12 | # Mac OS specific files 13 | .DS_Store 14 | .AppleDouble 15 | .LSOverride 16 | 17 | # VS Code specific files 18 | .vscode/ 19 | *.code-workspace 20 | 21 | # Environment variables 22 | .env 23 | *.env 24 | .env.* 25 | 26 | # Log files 27 | *.log 28 | 29 | # Temporary files 30 | *.tmp 31 | *.bak 32 | *.swp 33 | 34 | 35 | # Docker 36 | *.env 37 | .docker/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Maria Lazara 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /projeto-devops-fase-2/ec2.tf: -------------------------------------------------------------------------------- 1 | resource "aws_instance" "website_server" { 2 | ami = "ami-0b016c703b95ecbe4" #Amazon Linux 2 AMI 3 | instance_type = "t2.micro" 4 | key_name = "chave-site-prod" 5 | vpc_security_group_ids = [aws_security_group.website_sg.id] 6 | iam_instance_profile = "ECR-EC2-Role" 7 | 8 | tags = { 9 | Name = "website-server" 10 | Provisioned = "Terraform" 11 | Cliente = "Maria" 12 | } 13 | } 14 | 15 | ## Security Group 16 | resource "aws_security_group" "website_sg" { 17 | name = "website-sg" 18 | vpc_id = "vpc-0ff60a695425883cf" 19 | tags = { 20 | Name = "website-sg" 21 | Provisioned = "Terraform" 22 | Cliente = "Maria" 23 | } 24 | } 25 | 26 | resource "aws_vpc_security_group_ingress_rule" "allow_ssh" { 27 | security_group_id = aws_security_group.website_sg.id 28 | cidr_ipv4 = "seu-ip/32" 29 | from_port = 22 30 | ip_protocol = "tcp" 31 | to_port = 22 32 | } 33 | 34 | resource "aws_vpc_security_group_ingress_rule" "allow_http" { 35 | security_group_id = aws_security_group.website_sg.id 36 | cidr_ipv4 = "0.0.0.0/0" 37 | from_port = 80 38 | ip_protocol = "tcp" 39 | to_port = 80 40 | } 41 | 42 | resource "aws_vpc_security_group_ingress_rule" "allow_https" { 43 | security_group_id = aws_security_group.website_sg.id 44 | cidr_ipv4 = "0.0.0.0/0" 45 | from_port = 443 46 | ip_protocol = "tcp" 47 | to_port = 443 48 | } 49 | 50 | resource "aws_vpc_security_group_egress_rule" "allow_all_outbound" { 51 | security_group_id = aws_security_group.website_sg.id 52 | 53 | cidr_ipv4 = "0.0.0.0/0" 54 | ip_protocol = -1 55 | } 56 | 57 | -------------------------------------------------------------------------------- /projeto-devops-fase-3/.github/workflows/terraform.yaml: -------------------------------------------------------------------------------- 1 | name: Terraform CI/CD 2 | 3 | on: 4 | workflow_dispatch: # Allows manual triggering of the workflow 5 | inputs: 6 | apply: 7 | description: 'Executar o terraform apply?' 8 | required: true 9 | default: 'false' 10 | type: choice #Poderia ser do tipo boolean, mas escolhi choice para deixar mais amigável 11 | options: 12 | - true 13 | - false 14 | 15 | destroy: 16 | description: 'Destruir ambiente?' 17 | required: true 18 | default: 'false' 19 | type: choice 20 | options: 21 | - true 22 | - false 23 | 24 | plan_destroy: 25 | description: 'Planejar o destroy do ambiente?' 26 | required: true 27 | default: 'false' 28 | type: choice 29 | options: 30 | - true 31 | - false 32 | permissions: 33 | id-token: write 34 | contents: read 35 | 36 | jobs: 37 | job1: 38 | name: Terraform 39 | runs-on: ubuntu-latest 40 | steps: 41 | - name: Checkout 42 | uses: actions/checkout@v5.0.0 43 | 44 | - name: "Configure AWS Credentials" 45 | uses: aws-actions/configure-aws-credentials@v4.3.1 46 | with: 47 | role-to-assume: 48 | aws-region: 49 | 50 | - name: HashiCorp - Setup Terraform 51 | uses: hashicorp/setup-terraform@v3.1.2 52 | 53 | - name: Terraform Init 54 | run: terraform init 55 | 56 | - name: Terraform Validate 57 | run: terraform validate 58 | 59 | - name: Terraform Plan 60 | run: terraform plan -out=tfplan 61 | 62 | - name: Terraform Apply 63 | run: terraform apply -auto-approve tfplan 64 | if: github.event.inputs.apply == 'true' 65 | 66 | - name: Plan Destroy 67 | run: terraform plan -destroy -out=tfplandestroy 68 | if: github.event.inputs.plan_destroy == 'true' 69 | 70 | - name: Terraform Destroy 71 | run: terraform apply -destroy -auto-approve tfplandestroy 72 | if: github.event.inputs.destroy == 'true' -------------------------------------------------------------------------------- /projeto-devops-fase-4/repositorio-aplicacao/.github/workflows/deploy.yaml: -------------------------------------------------------------------------------- 1 | name: Pipeline CI/CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | id-token: write 10 | contents: read 11 | 12 | jobs: 13 | job1: 14 | name: build_ecr 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v5.0.0 19 | 20 | - name: "Configure AWS Credentials" 21 | uses: aws-actions/configure-aws-credentials@v4.3.1 22 | with: 23 | role-to-assume: arn:aws:iam:::role/GitHubActionsRepoApp 24 | aws-region: 25 | 26 | - name: Amazon ECR "Login" Action for GitHub Actions 27 | uses: aws-actions/amazon-ecr-login@v2.0.1 28 | 29 | - name: Build, Tag, and Push image to Amazon ECR 30 | run: | 31 | docker build -t meu-website:v1.0 . 32 | docker tag meu-website:v1.0 .dkr.ecr..amazonaws.com/site_prod:v1.0 33 | docker push .dkr.ecr..amazonaws.com/site_prod:v1.0 34 | 35 | job2: 36 | name: deploy_ec2 37 | needs: job1 38 | env: 39 | INSTANCE_KEY: ${{secrets.INSTANCE_KEY}} 40 | PUBLIC_IP: ${{secrets.PUBLIC_IP}} 41 | runs-on: ubuntu-latest 42 | steps: 43 | - name: Deploy EC2 SSH 44 | run: | 45 | echo "$INSTANCE_KEY" > chave-site.pem 46 | chmod 400 chave-site.pem 47 | ssh -i chave-site.pem -o StrictHostKeyChecking=no ec2-user@$PUBLIC_IP << EOF 48 | aws ecr get-login-password --region | docker login --username AWS --password-stdin .dkr.ecr..amazonaws.com 49 | docker pull .dkr.ecr..amazonaws.com/site_prod:v1.0 50 | echo "parando container antigo site" 51 | docker stop site || true 52 | echo "removendo container antigo site" 53 | docker rm site || true 54 | echo "rodando nova tag da imagem" 55 | docker run -d -p 80:80 --name site .dkr.ecr..amazonaws.com/site_prod:v1.0 56 | echo "Parabéns! Imagem foi atualizada!" 57 | docker ps 58 | EOF 59 | rm chave-site.pem 60 | -------------------------------------------------------------------------------- /projeto-devops-fase-1/website/js/script.js: -------------------------------------------------------------------------------- 1 | // Função para mostrar status do container 2 | function showStatus() { 3 | const statusSection = document.getElementById('status'); 4 | statusSection.scrollIntoView({ behavior: 'smooth' }); 5 | 6 | // Atualizar informações dinamicamente 7 | updateStatus(); 8 | } 9 | 10 | // Função para mostrar informações do sistema 11 | function showInfo() { 12 | const timestamp = new Date().toLocaleString('pt-BR'); 13 | const info = ` 14 | 🐳 Container Docker: Ativo 15 | ⚡ Servidor: Nginx 16 | 🌐 Porta: 80 17 | 📅 Deploy: ${timestamp} 18 | ☁️ Cloud: AWS EC2 19 | 🔄 Status: Online 20 | `; 21 | 22 | alert(info); 23 | } 24 | 25 | // Função para atualizar status em tempo real 26 | function updateStatus() { 27 | const containerStatus = document.getElementById('container-status'); 28 | const serverStatus = document.getElementById('server-status'); 29 | const environment = document.getElementById('environment'); 30 | 31 | // Simular verificação de status 32 | setTimeout(() => { 33 | containerStatus.textContent = 'Docker Ativo'; 34 | containerStatus.className = 'status-value active'; 35 | 36 | serverStatus.textContent = 'Nginx Online'; 37 | serverStatus.className = 'status-value active'; 38 | 39 | environment.textContent = 'AWS EC2 - Rodando'; 40 | environment.className = 'status-value active'; 41 | }, 1000); 42 | } 43 | 44 | // Inicialização quando a página carregar 45 | document.addEventListener('DOMContentLoaded', function() { 46 | console.log('🚀 DevOps Lab - Site carregado com sucesso!'); 47 | console.log('🐳 Container Docker ativo'); 48 | console.log('⚡ Servidor web rodando na porta 80'); 49 | 50 | // Smooth scroll para links de navegação 51 | const navLinks = document.querySelectorAll('.nav-link'); 52 | navLinks.forEach(link => { 53 | link.addEventListener('click', function(e) { 54 | e.preventDefault(); 55 | const targetId = this.getAttribute('href').substring(1); 56 | const targetElement = document.getElementById(targetId); 57 | 58 | if (targetElement) { 59 | targetElement.scrollIntoView({ behavior: 'smooth' }); 60 | } 61 | }); 62 | }); 63 | }); -------------------------------------------------------------------------------- /projeto-devops-fase-4/repositorio-aplicacao/.github/workflows/deploy2.yaml: -------------------------------------------------------------------------------- 1 | name: Pipeline CI/CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | permissions: 8 | contents: read 9 | id-token: write 10 | 11 | jobs: 12 | build-ecr: 13 | runs-on: ubuntu-latest 14 | outputs: 15 | registry: ${{ steps.login-ecr.outputs.registry }} 16 | image_tag: ${{ steps.build.outputs.image_tag }} 17 | image_uri: ${{ steps.build.outputs.image_uri }} 18 | steps: 19 | - uses: actions/checkout@v5.0.0 20 | 21 | - name: Configure AWS Credentials 22 | uses: aws-actions/configure-aws-credentials@v4.3.1 23 | with: 24 | role-to-assume: arn:aws:iam:::role/gitHubActionsECR 25 | aws-region: us-east-2 26 | 27 | - name: Login to Amazon ECR 28 | id: login-ecr 29 | uses: aws-actions/amazon-ecr-login@v2 30 | 31 | - name: Build, tag, and push docker image to Amazon ECR 32 | id: build 33 | env: 34 | REGISTRY: ${{ steps.login-ecr.outputs.registry }} 35 | REPOSITORY: site_prod 36 | ENVIRONMENT: ${{ github.ref_name == 'main' && 'prod' || 'dev' }} 37 | run: | 38 | COMMIT_SHA=$(echo $GITHUB_SHA | cut -c1-7) 39 | IMAGE_TAG=${ENVIRONMENT}-${COMMIT_SHA} 40 | docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG . 41 | docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG 42 | echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT 43 | echo "image_uri=$REGISTRY/$REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT 44 | 45 | deploy-ssh: 46 | runs-on: ubuntu-latest 47 | needs: build-ecr 48 | steps: 49 | - name: Deploy to EC2 via SSH 50 | env: 51 | IMAGE_TAG: ${{ needs.build-ecr.outputs.image_tag }} 52 | IMAGE_URI: ${{ needs.build-ecr.outputs.image_uri }} 53 | REGISTRY: ${{ needs.build-ecr.outputs.registry }} 54 | INSTANCE_KEY: ${{ secrets.INSTANCE_KEY }} 55 | ELASTIC_IP: ${{ secrets.ELASTIC_IP }} 56 | run: | 57 | echo $IMAGE_URI 58 | echo "$INSTANCE_KEY" > key.pem 59 | chmod 400 key.pem 60 | ssh -i key.pem -o StrictHostKeyChecking=no ec2-user@$ELASTIC_IP << EOF 61 | aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin $REGISTRY 62 | echo "baixando imagem $IMAGE_TAG" 63 | docker pull $IMAGE_URI 64 | echo "parando container antigo e iniciando novo" 65 | docker stop site || true 66 | docker rm site || true 67 | echo "iniciando container novo com a imagem $IMAGE_TAG" 68 | docker run -d -p 80:80 --name site $IMAGE_URI 69 | docker ps 70 | echo "deploy finalizado" 71 | EOF 72 | rm key.pem -------------------------------------------------------------------------------- /projeto-devops-fase-1/website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DevOps Lab - Maria Lazara 7 | 8 | 9 | 10 |
11 | 22 |
23 | 24 |
25 |
26 |
27 |

Parabéns! Você subiu o site!

28 |

Aprendendo DevOps com Docker e deploy na AWS

29 |
30 | 31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 |

🎯 Objetivo do Laboratório

39 |
40 |
41 |

🐳 Docker

42 |

Containerização da aplicação para garantir portabilidade e isolamento

43 |
44 |
45 |

☁️ AWS ECR

46 |

Gerenciamento seguro de imagens Docker na nuvem

47 |
48 |
49 |

🖥️ EC2

50 |

Deploy manual da aplicação em instância virtual na AWS

51 |
52 |
53 |
54 |
55 | 56 |
57 |
58 |

📊 Status do Sistema

59 |
60 |
61 | Container: 62 | Ativo 63 |
64 |
65 | Servidor: 66 | Nginx Rodando 67 |
68 |
69 | Ambiente: 70 | AWS EC2 71 |
72 |
73 |
74 |
75 |
76 | 77 |
78 |
79 |

© 2025 Maria Lazara - DevOps - Aprendendo na prática

80 |
81 |
82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /projeto-devops-fase-1/website/css/style.css: -------------------------------------------------------------------------------- 1 | /* Reset e Base */ 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | box-sizing: border-box; 6 | } 7 | 8 | :root { 9 | --primary-color: #6b46c1; /* Roxo principal */ 10 | --secondary-color: #9333ea; /* Roxo claro */ 11 | --accent-color: #a855f7; /* Roxo accent */ 12 | --dark-bg: #1a1a1a; /* Preto principal */ 13 | --darker-bg: #111111; /* Preto mais escuro */ 14 | --light-text: #ffffff; /* Texto claro */ 15 | --gray-text: #d1d5db; /* Texto cinza */ 16 | --border-color: #374151; /* Bordas */ 17 | --success-color: #10b981; /* Verde para status */ 18 | } 19 | 20 | body { 21 | font-family: 'Arial', sans-serif; 22 | background: var(--dark-bg); 23 | color: var(--light-text); 24 | line-height: 1.6; 25 | overflow-x: hidden; 26 | } 27 | 28 | /* Navbar */ 29 | .navbar { 30 | background: var(--darker-bg); 31 | padding: 1rem 0; 32 | position: fixed; 33 | top: 0; 34 | width: 100%; 35 | z-index: 1000; 36 | border-bottom: 2px solid var(--primary-color); 37 | } 38 | 39 | .nav-container { 40 | max-width: 1200px; 41 | margin: 0 auto; 42 | padding: 0 2rem; 43 | display: flex; 44 | justify-content: space-between; 45 | align-items: center; 46 | } 47 | 48 | .nav-title { 49 | color: var(--primary-color); 50 | font-size: 1.5rem; 51 | font-weight: bold; 52 | } 53 | 54 | .nav-menu { 55 | display: flex; 56 | gap: 2rem; 57 | } 58 | 59 | .nav-link { 60 | color: var(--gray-text); 61 | text-decoration: none; 62 | transition: color 0.3s ease; 63 | font-weight: 500; 64 | } 65 | 66 | .nav-link:hover { 67 | color: var(--accent-color); 68 | } 69 | 70 | /* Container */ 71 | .container { 72 | max-width: 1200px; 73 | margin: 0 auto; 74 | padding: 0 2rem; 75 | } 76 | 77 | /* Hero Section */ 78 | .hero { 79 | background: linear-gradient(135deg, var(--darker-bg) 0%, var(--primary-color) 100%); 80 | min-height: 100vh; 81 | display: flex; 82 | align-items: center; 83 | text-align: center; 84 | position: relative; 85 | } 86 | 87 | .hero::before { 88 | content: ''; 89 | position: absolute; 90 | top: 0; 91 | left: 0; 92 | right: 0; 93 | bottom: 0; 94 | background: url('data:image/svg+xml,') repeat; 95 | opacity: 0.1; 96 | } 97 | 98 | .hero .container { 99 | position: relative; 100 | z-index: 1; 101 | } 102 | 103 | .hero-title { 104 | font-size: 3.5rem; 105 | font-weight: bold; 106 | margin-bottom: 1rem; 107 | background: linear-gradient(45deg, var(--light-text), var(--accent-color)); 108 | -webkit-background-clip: text; 109 | -webkit-text-fill-color: transparent; 110 | background-clip: text; 111 | } 112 | 113 | .hero-subtitle { 114 | font-size: 1.2rem; 115 | color: var(--gray-text); 116 | margin-bottom: 2rem; 117 | max-width: 600px; 118 | margin-left: auto; 119 | margin-right: auto; 120 | } 121 | 122 | .hero-buttons { 123 | display: flex; 124 | gap: 1rem; 125 | justify-content: center; 126 | flex-wrap: wrap; 127 | } 128 | 129 | /* Buttons */ 130 | .btn { 131 | padding: 12px 24px; 132 | border: none; 133 | border-radius: 8px; 134 | font-size: 1rem; 135 | font-weight: 600; 136 | cursor: pointer; 137 | transition: all 0.3s ease; 138 | text-transform: uppercase; 139 | letter-spacing: 0.5px; 140 | } 141 | 142 | .btn.primary { 143 | background: var(--primary-color); 144 | color: var(--light-text); 145 | } 146 | 147 | .btn.primary:hover { 148 | background: var(--secondary-color); 149 | transform: translateY(-2px); 150 | box-shadow: 0 8px 20px rgba(107, 70, 193, 0.3); 151 | } 152 | 153 | .btn.secondary { 154 | background: transparent; 155 | color: var(--accent-color); 156 | border: 2px solid var(--accent-color); 157 | } 158 | 159 | .btn.secondary:hover { 160 | background: var(--accent-color); 161 | color: var(--light-text); 162 | transform: translateY(-2px); 163 | } 164 | 165 | /* Sections */ 166 | .section { 167 | padding: 5rem 0; 168 | border-top: 1px solid var(--border-color); 169 | } 170 | 171 | .section h2 { 172 | text-align: center; 173 | font-size: 2.5rem; 174 | margin-bottom: 3rem; 175 | color: var(--accent-color); 176 | } 177 | 178 | /* Card Grid */ 179 | .card-grid { 180 | display: grid; 181 | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 182 | gap: 2rem; 183 | margin-top: 2rem; 184 | } 185 | 186 | .card { 187 | background: var(--darker-bg); 188 | padding: 2rem; 189 | border-radius: 12px; 190 | border: 1px solid var(--border-color); 191 | transition: all 0.3s ease; 192 | position: relative; 193 | overflow: hidden; 194 | } 195 | 196 | .card::before { 197 | content: ''; 198 | position: absolute; 199 | top: 0; 200 | left: 0; 201 | right: 0; 202 | height: 3px; 203 | background: linear-gradient(90deg, var(--primary-color), var(--accent-color)); 204 | } 205 | 206 | .card:hover { 207 | transform: translateY(-5px); 208 | border-color: var(--primary-color); 209 | box-shadow: 0 15px 30px rgba(107, 70, 193, 0.2); 210 | } 211 | 212 | .card h3 { 213 | color: var(--accent-color); 214 | margin-bottom: 1rem; 215 | font-size: 1.3rem; 216 | } 217 | 218 | .card p { 219 | color: var(--gray-text); 220 | line-height: 1.6; 221 | } 222 | 223 | /* Status Grid */ 224 | .status-grid { 225 | display: grid; 226 | grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); 227 | gap: 1.5rem; 228 | margin-top: 2rem; 229 | } 230 | 231 | .status-item { 232 | background: var(--darker-bg); 233 | padding: 1.5rem; 234 | border-radius: 8px; 235 | border: 1px solid var(--border-color); 236 | display: flex; 237 | justify-content: space-between; 238 | align-items: center; 239 | } 240 | 241 | .status-label { 242 | color: var(--gray-text); 243 | font-weight: 600; 244 | } 245 | 246 | .status-value { 247 | color: var(--light-text); 248 | font-weight: bold; 249 | padding: 0.3rem 0.8rem; 250 | border-radius: 20px; 251 | background: var(--border-color); 252 | } 253 | 254 | .status-value.active { 255 | background: var(--success-color); 256 | color: var(--light-text); 257 | } 258 | 259 | /* Footer */ 260 | .footer { 261 | background: var(--darker-bg); 262 | padding: 2rem 0; 263 | border-top: 1px solid var(--border-color); 264 | text-align: center; 265 | color: var(--gray-text); 266 | } 267 | 268 | /* Responsive */ 269 | @media (max-width: 768px) { 270 | .nav-container { 271 | flex-direction: column; 272 | gap: 1rem; 273 | } 274 | 275 | .hero-title { 276 | font-size: 2.5rem; 277 | } 278 | 279 | .hero-buttons { 280 | flex-direction: column; 281 | align-items: center; 282 | } 283 | 284 | .btn { 285 | width: 200px; 286 | } 287 | } 288 | 289 | /* Animações */ 290 | @keyframes fadeInUp { 291 | from { 292 | opacity: 0; 293 | transform: translateY(30px); 294 | } 295 | to { 296 | opacity: 1; 297 | transform: translateY(0); 298 | } 299 | } 300 | 301 | .card { 302 | animation: fadeInUp 0.6s ease forwards; 303 | } 304 | 305 | .card:nth-child(1) { animation-delay: 0.1s; } 306 | .card:nth-child(2) { animation-delay: 0.2s; } 307 | .card:nth-child(3) { animation-delay: 0.3s; } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚀 Laboratório DevOps: Aprenda DevOps na Prática com Projetos Progressivos 2 | 3 | Olá! Eu sou Maria Lazara, DevOps Engineer, e vou te guiar nessa jornada DevOps. Sei que conceitos como containerização, IaC e CI/CD podem parecer intimidadores no início. Por isso, adoto uma didática simples e prática: vamos construir o conhecimento **de trás pra frente**. Isso significa começar pelo problema real – algo que você pode vivenciar e sentir a dor – e só depois buscar a solução, experimentando ferramentas como Docker, Terraform e GitHub Actions. No final, conectamos à teoria para solidificar o aprendizado. 4 | 5 | Meu foco é ensinar você a resolver problemas comuns que DevOps Engineers enfrentam diariamente, como "funciona na minha máquina, mas não no servidor" ou "deploys manuais causam downtime". Cada projeto aqui é uma peça de um quebra-cabeça: eles se conectam, aumentando a dificuldade gradualmente, simulando uma evolução real de um setup básico para um pipeline DevOps profissional. 6 | 7 | Este repositório contém 3 pastas, cada uma com um projeto independente, mas interligado: 8 | - **projeto-devops-fase-1**: O básico – containerize e deploy manual de um site estático na AWS. 9 | - **projeto-devops-fase-2**: Adicione automação de infraestrutura com Terraform (IaC). 10 | - **projeto-devops-fase-3**: Full automation com CI/CD usando GitHub Actions + Terraform + Docker. 11 | 12 | Cada pasta tem seu próprio `README.md` com passos detalhados, incluindo desafios para você simular problemas reais. Baixe o repo, siga os passos e experimente! 13 | 14 | *[Espaço para print: Estrutura do repositório no GitHub, mostrando as 3 pastas]* 15 | 16 | ## 📋 Pré-requisitos Técnicos 17 | 18 | **⚠️ IMPORTANTE**: Este laboratório é para pessoas com conhecimento básico-intermediário em desenvolvimento e infraestrutura. Não é um curso de fundamentos. 19 | 20 | ### Conhecimentos Obrigatórios: 21 | 22 | **🐧 Linux/Unix Básico** 23 | - Navegação no terminal (ls, cd, mkdir, cp, mv, rm) 24 | - Edição de arquivos (nano, vim ou VS Code) 25 | - Permissões básicas (chmod, sudo) 26 | - SSH e conexões remotas 27 | 28 | **☁️ AWS Básico** 29 | - Conceitos de EC2, IAM, VPC, Security Groups 30 | - Como criar instâncias e configurar acesso 31 | - AWS CLI configurado e funcional 32 | - Entender Free Tier e custos básicos 33 | 34 | **🐳 Docker Básico-Intermediário** 35 | - Diferença entre imagem e container 36 | - Comandos essenciais (build, run, push, pull) 37 | - Como escrever Dockerfile básico 38 | - Conceito de registries (Docker Hub, ECR) 39 | 40 | **🏗️ Terraform Básico** 41 | - Conceitos de Infrastructure as Code (IaC) 42 | - Comandos básicos (init, plan, apply, destroy) 43 | - Entender HCL (HashiCorp Configuration Language) 44 | - Conceito de state file 45 | 46 | **🔧 Git/GitHub** 47 | - Comandos básicos (clone, add, commit, push, pull) 48 | - Criação de repositórios 49 | - Conceitos de branches 50 | 51 | ### Auto-avaliação Rápida: 52 | ✅ Consigo criar uma instância EC2 e conectar via SSH? 53 | ✅ Sei fazer build de uma imagem Docker e executar? 54 | ✅ Já usei terraform apply para criar recursos? 55 | ✅ Domino comandos básicos do terminal Linux? 56 | 57 | **Se marcou menos de 4 ✅**: Estude os fundamentos primeiro antes de continuar. 58 | 59 | --- 60 | 61 | ## ❓ Por Que Essa Abordagem "De Trás Pra Frente"? 62 | Em vez de começar com teoria seca ("o que é Docker?"), vamos imitar a vida real: Você enfrenta um problema concreto, sente a frustração, e então descobre a ferramenta que resolve. Isso torna o aprendizado memorável e prático. Por exemplo: 63 | - Primeiro, vivencie o caos de um deploy manual. 64 | - Depois, busque soluções como "como automatizar isso?". 65 | - Finalmente, entenda a teoria por trás (ex.: "containers isolam dependências"). 66 | 67 | Isso é baseado em estudos de problemas: Cada projeto começa com uma situação real, como uma startup crescendo e enfrentando gargalos, inspirada em casos que vi em equipes reais. 68 | 69 | ## 🎯 Visão Geral dos Projetos 70 | Vamos construir um website estático simples (HTML/CSS/JS) e deployá-lo na AWS. Mas o foco não é o site – é o processo DevOps ao redor dele. Cada fase resolve problemas da anterior, adicionando camadas de automação. 71 | 72 | ### Projeto 1: Containerização com Docker e Deploy Manual na AWS (Nível Básico) 73 | - **Problema Real**: Imagine você em uma pequena equipe: O dev altera o código, mas no servidor AWS, "não funciona" por causa de dependências diferentes. Deploys envolvem SSH manual, levando a erros e tempo perdido. 74 | - **Solução Prática**: Use Docker para "empacotar" o site em um container portátil. Crie um ECR na AWS, push a imagem e deploy manual na EC2. 75 | - **Ferramentas Aprendidas**: Docker, AWS CLI, ECR, EC2, Security Groups. 76 | - **Conexão**: Isso resolve o "funciona na minha máquina", mas ainda é manual – preparando o terreno para automação na Fase 2. 77 | - **Tempo Estimado**: 2-3 horas. 78 | - **Desafio Inicial**: Tente deployar manualmente sem Docker e veja os erros de dependências. 79 | 80 | *[Espaço para print: Diagrama simples da arquitetura do Projeto 1, mostrando código local → Docker → ECR → EC2 → Browser]* 81 | 82 | ### Projeto 2: Automatização de Infraestrutura com Terraform (IaC) (Nível Intermediário) 83 | - **Problema Real**: Agora a startup cresce: Você precisa recriar ambientes (dev/staging/prod) rapidamente, mas cliques manuais no console AWS causam inconsistências, erros e "drift" (mudanças não rastreadas). Um deploy de emergência falha porque uma configuração foi esquecida. 84 | - **Solução Prática**: Trate a infra como código com Terraform. Declare recursos como EC2, ECR e IAM Roles em arquivos HCL, e o Terraform provisiona tudo automaticamente. 85 | - **Ferramentas Aprendidas**: Terraform (init/plan/apply/destroy), backends remotos (S3 para state), outputs para integração. 86 | - **Conexão**: Integra com o Docker do Projeto 1 – agora a infra é reproduzível, mas o deploy ainda requer SSH manual. Isso motiva a full automation na Fase 3. 87 | - **Tempo Estimado**: 2-4 horas. 88 | - **Desafio Inicial**: Tente recriar manualmente o ambiente do Projeto 1 em uma nova região e note os pontos de dor. 89 | 90 | *[Espaço para print: Diagrama da arquitetura do Projeto 2, mostrando arquivos Terraform → AWS Infra (EC2/ECR) → Deploy Docker]* 91 | 92 | ### Projeto 3: Automatização Completa com CI/CD (GitHub Actions + Terraform + Docker) (Nível Avançado) 93 | - **Problema Real**: Com múltiplos devs, changes diárias viram caos: Deploys manuais criam gargalos, erros humanos e falta de auditabilidade. Um pico de tráfego exige update rápido, mas conflitos no Terraform state causam downtime. 94 | - **Solução Prática**: Separe repos (app e infra), use GitHub Actions para pipelines CI/CD. Push no código dispara builds Docker, plans Terraform e deploys com aprovações manuais para segurança. 95 | - **Ferramentas Aprendidas**: GitHub Actions (workflows YAML, secrets, aprovações), integração multi-repo. 96 | - **Conexão**: Une tudo: Docker do Projeto 1 + Terraform do Projeto 2 em um fluxo automatizado. Agora, é um pipeline DevOps real, escalável para equipes. 97 | - **Tempo Estimado**: 3-5 horas. 98 | - **Desafio Inicial**: Simule deploys simultâneos manuais no setup do Projeto 2 e veja conflitos. 99 | 100 | *[Espaço para print: Diagrama completo da arquitetura do Projeto 3, mostrando Repos GitHub → Actions CI/CD → AWS Infra + Deploy]* 101 | 102 | ## 🔧 Como Começar 103 | 1. **Clone o Repositório**: 104 | ```bash 105 | git clone https://github.com/marialazara/devops-projects.git 106 | cd seu-repo-devops 107 | ``` 108 | 2. **Escolha uma Fase**: Comece pela pasta `projeto-devops-fase-1` e avance. Cada README tem pré-requisitos, passos e troubleshooting. 109 | 3. **Ambiente**: Certifique-se de ter uma conta AWS gratuita (cuidado com custos – use Free Tier). Instale ferramentas como Docker, Terraform e AWS CLI conforme descrito. 110 | 4. **Dicas Gerais**: 111 | - Use VS Code para editar arquivos. 112 | - Sempre teste localmente antes de apply/destroy. 113 | - Limpe recursos AWS no final para evitar custos! 114 | 5. **Personalize**: Substitua placeholders (ex.: regiões AWS, nomes de repos) com os seus. 115 | 116 | ## 🎓 Conceitos Aprendidos no Geral 117 | Ao final, você dominará ferramentas chave de um DevOps Engineer: 118 | - **Containerização** (Docker): Resolve inconsistências de ambiente. 119 | - **IaC** (Terraform): Automatiza e versiona infra. 120 | - **CI/CD** (GitHub Actions): Orquestra fluxos para deploys rápidos e seguros. 121 | - **Melhores Práticas**: Secrets management, aprovações, state locking, drift detection. 122 | 123 | Esses projetos simulam uma progressão real: De manual para IaC para automatizado, resolvendo problemas como escalabilidade, colaboração e erros humanos. 124 | 125 | ## 📚 Recursos Adicionais 126 | - [Documentação Docker](https://docs.docker.com/) 127 | - [Terraform Learning](https://learn.hashicorp.com/terraform) 128 | - [GitHub Actions Docs](https://docs.github.com/en/actions) 129 | - Livros: "The DevOps Handbook" para teoria aplicada. 130 | - Comunidades: Reddit r/devops, Stack Overflow. 131 | 132 | ## 🧹 Notas Finais 133 | Lembre-se: DevOps é sobre cultura tanto quanto ferramentas – automatize para liberar tempo para inovação. Se travar, pesquise o erro (ex.: "Terraform AMI not found") – isso treina skills reais! 134 | 135 | Desenvolvido com ❤️ por Maria Lazara. Assista ao meu vídeo explicativo no YouTube, onde falo desses projetos e do mundo DevOps: [Link para o Vídeo](https://www.youtube.com/@marialazaradev). Compartilhe seu progresso nos comentários! 🚀 136 | -------------------------------------------------------------------------------- /projeto-devops-fase-4/README.md: -------------------------------------------------------------------------------- 1 | # Projeto DevOps - Automação de Deploy de Site em Instância EC2 2 | 3 | ## Descrição 4 | Este projeto implementa uma pipeline CI/CD utilizando GitHub Actions para automatizar o build, push de uma imagem Docker para o Amazon ECR e o deploy de um site estático em uma instância EC2 na AWS. O site é composto por arquivos HTML, CSS e JavaScript, containerizados via Docker. A pipeline é acionada em pushes para a branch `main`, garantindo integração contínua e entrega contínua com foco em segurança e eficiência, seguindo melhores práticas de DevSecOps, como uso de credenciais temporárias via OIDC e segredos gerenciados. 5 | 6 | Essa abordagem promove escalabilidade, com o uso de Infrastructure as Code (IaC) implícito na configuração da pipeline, e reliability através de dependências entre jobs para evitar deploys falhos. Para mais detalhes sobre GitHub Actions, consulte a [documentação oficial](https://docs.github.com/en/actions). 7 | 8 | ## Assista ao Tutorial em Vídeo 9 | Para complementar esta documentação, elaborei um vídeo completo que explica passo a passo a implementação da pipeline CI/CD, desde a configuração inicial até o deploy na instância EC2, com foco em melhores práticas de DevOps, como uso de credenciais temporárias via OIDC e tagging dinâmico de imagens Docker. 10 | 11 | Esse vídeo faz parte da série "DevOps na Prática", e corresponde à parte 4 de uma playlist abrangente, que cobre todo o processo desde os conceitos iniciais até as otimizações avançadas, incluindo integração com ferramentas como Terraform e SonarQube. Acesse a playlist completa aqui: [Playlist DevOps na Prática](https://youtube.com/playlist?list=PLOCRt8ucq6xNSMUvfTxnk-M4mk9Etwpy6&si=LOoW5N9Xc6-QViKN). Recomendo assistir para uma visão prática e visual. 12 | 13 | ## Pré-requisitos 14 | 15 | - Conta AWS com permissões para ECR e EC2. 16 | - Repositório GitHub com segredos configurados: `INSTANCE_KEY` (chave SSH privada) e `PUBLIC_IP` (IP público da instância EC2). 17 | - Role IAM no AWS para GitHub Actions (usando OIDC para autenticação segura, sem chaves de acesso permanentes). Veja [documentação AWS para GitHub Actions](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html). 18 | - Instância EC2 com Docker instalado e acesso SSH configurado para o usuário `ec2-user`. 19 | - Repositório ECR criado na região `us-east-2`. 20 | 21 | ## Estrutura do Repositório 22 | 23 | - **website/**: Contém os arquivos do site: 24 | - `index.html`: Página principal. 25 | - Arquivos CSS e JavaScript para estilização e funcionalidades. 26 | - **Dockerfile**: Arquivo para build da imagem Docker do site, baseado em uma imagem web server como Nginx ou similar (exemplo: copia arquivos para `/usr/share/nginx/html`). 27 | - **.github/workflows/deploy.yaml**: Workflow do GitHub Actions para a pipeline CI/CD. 28 | 29 | ## Pipeline CI/CD 30 | 31 | A pipeline é definida no arquivo `deploy.yaml` e consiste em dois jobs sequenciais: build e push para ECR, seguido de deploy via SSH na EC2. 32 | 33 | ```yaml 34 | name: Pipeline CI/CD 35 | 36 | on: 37 | push: 38 | branches: 39 | - main 40 | 41 | permissions: 42 | id-token: write 43 | contents: read 44 | 45 | jobs: 46 | job1: 47 | name: build_ecr 48 | runs-on: ubuntu-latest 49 | steps: 50 | - name: Checkout 51 | uses: actions/checkout@v5.0.0 52 | 53 | - name: "Configure AWS Credentials" 54 | uses: aws-actions/configure-aws-credentials@v4.3.1 55 | with: 56 | role-to-assume: arn:aws:iam:::role/GitHubActionsRepoApp 57 | aws-region: us-east-2 58 | 59 | - name: Amazon ECR "Login" Action for GitHub Actions 60 | uses: aws-actions/amazon-ecr-login@v2.0.1 61 | 62 | - name: Build, Tag, and Push image to Amazon ECR 63 | run: | 64 | docker build -t meu-website:v1.0 . 65 | docker tag meu-website:v1.0 .dkr.ecr.us-east-2.amazonaws.com/site_prod:v1.0 66 | docker push .dkr.ecr.us-east-2.amazonaws.com/site_prod:v1.0 67 | 68 | job2: 69 | name: deploy_ec2 70 | needs: job1 71 | env: 72 | INSTANCE_KEY: ${{secrets.INSTANCE_KEY}} 73 | PUBLIC_IP: ${{secrets.PUBLIC_IP}} 74 | runs-on: ubuntu-latest 75 | steps: 76 | - name: Deploy EC2 SSH 77 | run: | 78 | echo "$INSTANCE_KEY" > chave-site.pem 79 | chmod 400 chave-site.pem 80 | ssh -i chave-site.pem -o StrictHostKeyChecking=no ec2-user@$PUBLIC_IP << EOF 81 | aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin .dkr.ecr.us-east-2.amazonaws.com 82 | docker pull .dkr.ecr.us-east-2.amazonaws.com/site_prod:v1.0 83 | echo "parando container antigo site" 84 | docker stop site || true 85 | echo "removendo container antigo site" 86 | docker rm site || true 87 | echo "rodando nova tag da imagem" 88 | docker run -d -p 80:80 --name site .dkr.ecr.us-east-2.amazonaws.com/site_prod:v1.0 89 | echo "Parabéns! Imagem foi atualizada!" 90 | docker ps 91 | EOF 92 | rm chave-site.pem 93 | ``` 94 | 95 | **Observações de Segurança:** 96 | - Substitua `` pelo ID da sua conta AWS. 97 | - Use segredos do GitHub para armazenar chaves sensíveis, evitando exposição no código. 98 | - A opção `-o StrictHostKeyChecking=no` é usada para automação 99 | 100 | ## Explicação das Etapas 101 | 102 | 1. **Trigger**: A pipeline é acionada automaticamente em pushes para a branch `main`. 103 | 104 | 2. **Job 1 - build_ecr**: 105 | - **Checkout**: Baixa o código do repositório. 106 | - **Configure AWS Credentials**: Assume uma role IAM via OIDC para autenticação segura sem chaves de acesso. 107 | - **ECR Login**: Realiza login no ECR usando credenciais temporárias. 108 | - **Build, Tag e Push**: Constrói a imagem Docker a partir do `Dockerfile`, tagga com a versão e envia para o repositório ECR. 109 | 110 | 3. **Job 2 - deploy_ec2** (dependente do Job 1): 111 | - Usa segredos para chave SSH e IP da EC2. 112 | - Cria um arquivo temporário com a chave SSH e configura permissões. 113 | - Conecta via SSH à instância EC2 e executa comandos para: 114 | - Login no ECR. 115 | - Pull da nova imagem. 116 | - Parada e remoção do container antigo (se existir). 117 | - Execução do novo container mapeando porta 80. 118 | - Verificação com `docker ps`. 119 | - Remove a chave temporária para evitar vazamentos. 120 | 121 | 122 | 123 | ## Pipeline CI/CD Customizável (deploy2.yaml) 124 | 125 | ### Descrição 126 | 127 | Esta é uma versão customizável e ligeiramente mais complexa da pipeline CI/CD, definida no arquivo `deploy2.yaml`. Ela aprimora a automação de build, tag e push de imagens Docker para o Amazon ECR, seguida de deploy em uma instância EC2 via SSH. As melhorias incluem: tagging dinâmico da imagem com base no commit SHA e ambiente (prod ou dev, dependendo da branch), uso de outputs para passar variáveis entre jobs, e maior flexibilidade para ambientes multi-branch. Isso segue melhores práticas de DevSecOps, como uso de credenciais temporárias via OIDC, variáveis de ambiente para configuração dinâmica, e atomicidade via dependências de jobs, reduzindo toil e melhorando a rastreabilidade (ex.: logs com tags únicas). Para detalhes sobre outputs em GitHub Actions, consulte a [documentação oficial](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idoutputs). 128 | 129 | Essa versão é ideal para cenários onde se deseja escalabilidade, como integração com múltiplos ambientes ou integração com ferramentas como Terraform para provisionamento dinâmico de recursos. Ela mantém foco em segurança, utilizando segredos gerenciados e permissões mínimas (`contents: read` e `id-token: write`). 130 | 131 | ### Pré-requisitos 132 | 133 | Mesmos da pipeline original, com adição de: 134 | - Configuração de branches adicionais (ex.: `dev` para ambientes de teste), ajustando a lógica de `ENVIRONMENT`. 135 | - Repositório ECR com permissões para push de tags dinâmicas. 136 | 137 | ### Pipeline CI/CD Customizável 138 | 139 | O workflow é acionado em pushes para `main`, mas pode ser expandido para outras branches. Aqui está o conteúdo do `deploy2.yaml` (com dados sensíveis substituídos por placeholders): 140 | 141 | ```yaml 142 | name: Pipeline CI/CD 143 | 144 | on: 145 | push: 146 | branches: 147 | - main 148 | permissions: 149 | contents: read 150 | id-token: write 151 | 152 | jobs: 153 | build-ecr: 154 | runs-on: ubuntu-latest 155 | outputs: 156 | registry: ${{ steps.login-ecr.outputs.registry }} 157 | image_tag: ${{ steps.build.outputs.image_tag }} 158 | image_uri: ${{ steps.build.outputs.image_uri }} 159 | steps: 160 | - uses: actions/checkout@v5.0.0 161 | 162 | - name: Configure AWS Credentials 163 | uses: aws-actions/configure-aws-credentials@v4.3.1 164 | with: 165 | role-to-assume: arn:aws:iam:::role/gitHubActionsECR 166 | aws-region: us-east-2 167 | 168 | - name: Login to Amazon ECR 169 | id: login-ecr 170 | uses: aws-actions/amazon-ecr-login@v2 171 | 172 | - name: Build, tag, and push docker image to Amazon ECR 173 | id: build 174 | env: 175 | REGISTRY: ${{ steps.login-ecr.outputs.registry }} 176 | REPOSITORY: site_prod 177 | ENVIRONMENT: ${{ github.ref_name == 'main' && 'prod' || 'dev' }} 178 | run: | 179 | COMMIT_SHA=$(echo $GITHUB_SHA | cut -c1-7) 180 | IMAGE_TAG=${ENVIRONMENT}-${COMMIT_SHA} 181 | docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG . 182 | docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG 183 | echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT 184 | echo "image_uri=$REGISTRY/$REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT 185 | 186 | deploy-ssh: 187 | runs-on: ubuntu-latest 188 | needs: build-ecr 189 | steps: 190 | - name: Deploy to EC2 via SSH 191 | env: 192 | IMAGE_TAG: ${{ needs.build-ecr.outputs.image_tag }} 193 | IMAGE_URI: ${{ needs.build-ecr.outputs.image_uri }} 194 | REGISTRY: ${{ needs.build-ecr.outputs.registry }} 195 | INSTANCE_KEY: ${{ secrets.INSTANCE_KEY }} 196 | ELASTIC_IP: ${{ secrets.ELASTIC_IP }} 197 | run: | 198 | echo $IMAGE_URI 199 | echo "$INSTANCE_KEY" > key.pem 200 | chmod 400 key.pem 201 | ssh -i key.pem -o StrictHostKeyChecking=no ec2-user@$ELASTIC_IP << EOF 202 | aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin $REGISTRY 203 | echo "baixando imagem $IMAGE_TAG" 204 | docker pull $IMAGE_URI 205 | echo "parando container antigo e iniciando novo" 206 | docker stop site || true 207 | docker rm site || true 208 | echo "iniciando container novo com a imagem $IMAGE_TAG" 209 | docker run -d -p 80:80 --name site $IMAGE_URI 210 | docker ps 211 | echo "deploy finalizado" 212 | EOF 213 | rm key.pem 214 | ``` 215 | 216 | ### Explicação das Etapas 217 | 218 | 1. **Trigger e Permissões**: Acionado em pushes para `main`, com permissões mínimas para leitura de conteúdo e geração de ID tokens OIDC. 219 | 220 | 2. **Job build-ecr**: 221 | - **Checkout**: Baixa o código. 222 | - **Configure AWS Credentials**: Assume role IAM via OIDC. 223 | - **Login to ECR**: Gera credenciais temporárias e expõe `registry` como output. 224 | - **Build, Tag e Push**: Define ambiente dinamicamente (`prod` para `main`, `dev` otherwise), gera tag única com SHA do commit para versionamento imutável, constrói e pusha a imagem. Outputs (`image_tag`, `image_uri`) são passados para o próximo job, promovendo decoupling. 225 | 226 | 3. **Job deploy-ssh** (dependente de build-ecr): 227 | - Usa outputs do job anterior para imagem dinâmica. 228 | - Cria chave SSH temporária com permissões seguras. 229 | - Via SSH na EC2: Loga no ECR, puxa a imagem específica, para/remove container antigo, inicia novo mapeando porta 80, verifica com `docker ps`. 230 | - Remove chave para evitar exposição. 231 | 232 | Essa estrutura melhora reliability com tags imutáveis (facilitando rollbacks) e scalability para multi-ambientes, alinhando com SRE principles como SLOs para deploy time (monitore via Prometheus). 233 | 234 | ### Melhorias em Relação à Versão Original 235 | 236 | - **Tagging Dinâmico**: Usa commit SHA para tags únicas, evitando sobrescrita e permitindo traceability (ex.: rollback para tag específica via `docker pull`). 237 | - **Ambientes Customizáveis**: Lógica condicional para `prod/dev`, expansível para mais branches com GitOps tools como ArgoCD. 238 | - **Outputs entre Jobs**: Melhora modularidade, facilitando adição de jobs (ex.: testes com SonarQube antes de deploy). 239 | - **Flexibilidade**: Fácil integração com IaC (ex.: Terraform para criar ECR/EC2) ou monitoramento (ex.: Datadog para alertas em falhas). 240 | 241 | Para testes locais, build com `docker build -t /:prod- .` e simule deploy manual. Para otimizações, integre Snyk para scans de vulnerabilidades no build (doc: [Snyk GitHub Actions](https://docs.snyk.io/integrations/ci-cd-integrations/github-actions-integration)). -------------------------------------------------------------------------------- /projeto-devops-fase-1/README.md: -------------------------------------------------------------------------------- 1 | # 🚀 Laboratório DevOps - Projeto 1: Containerização com Docker e Deploy Manual na AWS 2 | 3 | ## 📋 Índice 4 | 1. [Visão Geral](#visão-geral) 5 | 2. [Pré-requisitos](#pré-requisitos) 6 | 3. [Arquitetura do Projeto](#arquitetura-do-projeto) 7 | 4. [Fase 1: Preparação do Ambiente Local](#fase-1-preparação-do-ambiente-local) 8 | 5. [Fase 2: Containerização com Docker](#fase-2-containerização-com-docker) 9 | 6. [Fase 3: Teste Local do Container](#fase-3-teste-local-do-container) 10 | 7. [Fase 4: Configuração do Amazon ECR](#fase-4-configuração-do-amazon-ecr) 11 | 8. [Fase 5: Push da Imagem para o ECR](#fase-5-push-da-imagem-para-o-ecr) 12 | 9. [Fase 6: Provisionamento da Instância EC2](#fase-6-provisionamento-da-instância-ec2) 13 | 10. [Fase 7: Deploy na EC2](#fase-7-deploy-na-ec2) 14 | 11. [Verificação e Testes](#verificação-e-testes) 15 | 12. [Troubleshooting](#troubleshooting) 16 | 13. [Limpeza de Recursos](#limpeza-de-recursos) 17 | 18 | --- 19 | 20 | ## 🎯 Visão Geral 21 | 22 | ### O que vamos construir? 23 | Neste laboratório, você aprenderá a containerizar um website estático (HTML, CSS e JavaScript) usando Docker e implantá-lo manualmente em uma instância EC2 na AWS, utilizando o Amazon ECR (Elastic Container Registry) para gerenciamento de imagens. 24 | 25 | ### Por que isso é importante? 26 | - **Portabilidade**: Seu site funcionará da mesma forma em qualquer ambiente 27 | - **Isolamento**: Elimina problemas de "funciona na minha máquina" 28 | - **Escalabilidade**: Base para futuras implementações mais complexas 29 | - **Padrão da Indústria**: Docker é amplamente utilizado no mercado 30 | 31 | ### Tempo estimado: 2-3 horas 32 | 33 | --- 34 | 35 | ## 🔧 Pré-requisitos 36 | 37 | ### Ferramentas Necessárias 38 | 39 | #### 1. **Docker Desktop** 40 | - **Windows/Mac**: Baixe em [docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop) 41 | - **Linux**: Instale via terminal: 42 | ```bash 43 | curl -fsSL https://get.docker.com -o get-docker.sh 44 | sudo sh get-docker.sh 45 | ``` 46 | 47 | Para verificar a instalação: 48 | ```bash 49 | docker --version 50 | ``` 51 | 52 | *[Espaço para print: Resultado do comando docker --version]* 53 | 54 | #### 2. **AWS CLI** 55 | Instale seguindo a [documentação oficial](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 56 | 57 | Para verificar: 58 | ```bash 59 | aws --version 60 | ``` 61 | 62 | *[Espaço para print: Resultado do comando aws --version]* 63 | 64 | #### 3. **Conta AWS** 65 | - Crie uma conta gratuita em [aws.amazon.com](https://aws.amazon.com) 66 | - ⚠️ **Importante**: Alguns recursos podem gerar custos. Use o Free Tier quando possível 67 | 68 | #### 4. **Editor de Código** 69 | - Recomendado: [Visual Studio Code](https://code.visualstudio.com/) 70 | - Extensões úteis: Docker, AWS Toolkit 71 | 72 | ### Estrutura do Projeto 73 | ``` 74 | meu-projeto/ 75 | ├── website/ 76 | │ ├── index.html 77 | │ ├── styles.css 78 | │ ├── script.js 79 | │ └── assets/ 80 | │ └── (imagens, fontes, etc.) 81 | └── Dockerfile (vamos criar) 82 | ``` 83 | 84 | --- 85 | 86 | ## 🏗️ Arquitetura do Projeto 87 | 88 | ``` 89 | ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ 90 | │ Código Local │────▶│ Docker Image │────▶│ Amazon ECR │ 91 | │ (HTML/CSS/JS) │ │ (Container) │ │ (Registry) │ 92 | └─────────────────┘ └─────────────────┘ └─────────────────┘ 93 | │ 94 | ▼ 95 | ┌─────────────────┐ ┌─────────────────┐ 96 | │ Browser │◀────│ Amazon EC2 │ 97 | │ (User Access) │ │ (Container) │ 98 | └─────────────────┘ └─────────────────┘ 99 | ``` 100 | 101 | --- 102 | 103 | ## 📦 Fase 1: Preparação do Ambiente Local 104 | 105 | ### Passo 1.1: Verificar estrutura do projeto 106 | 107 | Navegue até o diretório do seu projeto: 108 | ```bash 109 | cd caminho/para/seu/projeto 110 | ls -la 111 | ``` 112 | 113 | Você deve ver a pasta `website/` com seus arquivos: 114 | ```bash 115 | ls -la website/ 116 | ``` 117 | 118 | *[Espaço para print: Estrutura de arquivos do projeto]* 119 | 120 | ### Passo 1.2: Testar o website localmente (opcional) 121 | 122 | Você pode abrir o `index.html` diretamente no navegador para verificar se está funcionando: 123 | ```bash 124 | # No Mac 125 | open website/index.html 126 | 127 | # No Linux 128 | xdg-open website/index.html 129 | 130 | # No Windows (PowerShell) 131 | start website/index.html 132 | ``` 133 | 134 | *[Espaço para print: Website funcionando no navegador]* 135 | 136 | --- 137 | 138 | ## 🐳 Fase 2: Containerização com Docker 139 | 140 | ### Passo 2.1: Criar o Dockerfile 141 | 142 | Na raiz do projeto (mesmo nível da pasta `website/`), crie um arquivo chamado `Dockerfile`: 143 | 144 | ```bash 145 | touch Dockerfile 146 | ``` 147 | 148 | ### Passo 2.2: Escrever o Dockerfile 149 | 150 | Abra o Dockerfile no seu editor e adicione: 151 | 152 | ```dockerfile 153 | # Imagem base - Nginx Alpine (leve e eficiente) 154 | FROM nginx:alpine 155 | 156 | # Copia os arquivos do website para o diretório do Nginx 157 | COPY website/ /usr/share/nginx/html/ 158 | 159 | # Expõe a porta 80 (documentação - não abre a porta realmente) 160 | EXPOSE 80 161 | 162 | # Comando padrão quando o container iniciar 163 | CMD ["nginx", "-g", "daemon off;"] 164 | ``` 165 | 166 | #### 🎓 Entendendo cada linha: 167 | 168 | - **FROM nginx:alpine**: Define a imagem base. Alpine é uma versão Linux super leve 169 | - **COPY**: Copia arquivos do host para dentro da imagem 170 | - **EXPOSE**: Documenta qual porta o container usa 171 | - **CMD**: Define o comando padrão ao iniciar o container 172 | 173 | *[Espaço para print: Dockerfile criado no editor]* 174 | 175 | ### Passo 2.3: Construir a imagem Docker 176 | 177 | No terminal, na raiz do projeto, execute: 178 | 179 | ```bash 180 | docker build -t meu-website:v1.0 . 181 | ``` 182 | 183 | #### 🎓 Entendendo o comando: 184 | - **docker build**: Comando para construir uma imagem 185 | - **-t meu-website:v1.0**: Tag (nome:versão) da imagem 186 | - **.**: Contexto de build (diretório atual) 187 | 188 | Você verá a saída do processo de build: 189 | ``` 190 | [+] Building 10.5s (8/8) FINISHED 191 | => [internal] load build definition from Dockerfile 192 | => transferring dockerfile: 370B 193 | => [internal] load .dockerignore 194 | => [internal] load metadata for docker.io/library/nginx:alpine 195 | => [1/3] FROM docker.io/library/nginx:alpine 196 | => [2/3] RUN rm -rf /usr/share/nginx/html/* 197 | => [3/3] COPY website/ /usr/share/nginx/html/ 198 | => exporting to image 199 | => naming to docker.io/library/meu-website:v1.0 200 | ``` 201 | 202 | *[Espaço para print: Processo de build do Docker]* 203 | 204 | ### Passo 2.4: Verificar a imagem criada 205 | 206 | ```bash 207 | docker images 208 | ``` 209 | 210 | Você deve ver sua imagem listada: 211 | ``` 212 | REPOSITORY TAG IMAGE ID CREATED SIZE 213 | meu-website v1.0 abc123def456 30 seconds ago 23.5MB 214 | ``` 215 | 216 | *[Espaço para print: Lista de imagens Docker]* 217 | 218 | --- 219 | 220 | ## 🧪 Fase 3: Teste Local do Container 221 | 222 | ### Passo 3.1: Executar o container localmente 223 | 224 | ```bash 225 | docker run -d -p 8080:80 --name meu-website-container meu-website:v1.0 226 | ``` 227 | 228 | #### 🎓 Entendendo o comando: 229 | - **docker run**: Cria e executa um container 230 | - **-d**: Executa em background (detached) 231 | - **-p 8080:80**: Mapeia porta 8080 do host para porta 80 do container 232 | - **--name**: Nome do container 233 | - **meu-website:v1.0**: Imagem a ser usada 234 | 235 | ### Passo 3.2: Verificar se o container está rodando 236 | 237 | ```bash 238 | docker ps 239 | ``` 240 | 241 | Você verá algo como: 242 | ``` 243 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 244 | xyz789abc123 meu-website:v1.0 "nginx -g 'daemon..." 10 seconds ago Up 9 seconds 0.0.0.0:8080->80/tcp meu-website-container 245 | ``` 246 | 247 | *[Espaço para print: Container em execução]* 248 | 249 | ### Passo 3.3: Testar no navegador 250 | 251 | Abra seu navegador e acesse: 252 | ``` 253 | http://localhost:8080 254 | ``` 255 | 256 | Você deve ver seu website funcionando! 🎉 257 | 258 | *[Espaço para print: Website rodando via Docker no localhost:8080]* 259 | 260 | ### Passo 3.4: Verificar logs do container (opcional) 261 | 262 | ```bash 263 | docker logs meu-website-container 264 | ``` 265 | 266 | ### Passo 3.5: Parar e remover o container de teste 267 | 268 | ```bash 269 | # Parar o container 270 | docker stop meu-website-container 271 | 272 | # Remover o container 273 | docker rm meu-website-container 274 | ``` 275 | 276 | --- 277 | 278 | ## ☁️ Fase 4: Configuração do Amazon ECR 279 | 280 | ### Passo 4.1: Acessar o Console AWS 281 | 282 | 1. Acesse [console.aws.amazon.com](https://console.aws.amazon.com) 283 | 2. Faça login com suas credenciais 284 | 285 | *[Espaço para print: Console AWS]* 286 | 287 | ### Passo 4.2: Navegar para o ECR 288 | 289 | 1. Na barra de busca superior, digite "ECR" 290 | 2. Clique em "Elastic Container Registry" 291 | 292 | *[Espaço para print: Busca pelo ECR]* 293 | 294 | ### Passo 4.3: Criar um repositório 295 | 296 | 1. Clique em "Create repository" 297 | 2. Configure: 298 | - **Visibility settings**: Private 299 | - **Repository name**: `meu-website` 300 | - **Tag immutability**: Disabled (padrão) 301 | - **Scan on push**: Enabled (recomendado para segurança) 302 | 3. Clique em "Create repository" 303 | 304 | *[Espaço para print: Formulário de criação do repositório]* 305 | 306 | ### Passo 4.4: Anotar a URI do repositório 307 | 308 | Após criar, você verá algo como: 309 | ``` 310 | 123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website 311 | ``` 312 | 313 | ⚠️ **Importante**: Copie e guarde esta URI, você precisará dela! 314 | 315 | *[Espaço para print: Repositório criado com a URI visível]* 316 | 317 | --- 318 | 319 | ## 📤 Fase 5: Push da Imagem para o ECR 320 | 321 | ### Passo 5.1: Configurar AWS CLI 322 | 323 | Se ainda não configurou, execute: 324 | ```bash 325 | aws configure 326 | ``` 327 | 328 | Você precisará fornecer: 329 | - **AWS Access Key ID**: Obtida no IAM 330 | - **AWS Secret Access Key**: Obtida no IAM 331 | - **Default region**: ex: us-east-1 332 | - **Default output format**: json 333 | 334 | ### Passo 5.2: Autenticar Docker com ECR 335 | 336 | ```bash 337 | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com 338 | ``` 339 | 340 | ⚠️ **Substitua**: 341 | - `us-east-1` pela sua região 342 | - `123456789012` pelo seu Account ID 343 | 344 | Você deve ver: 345 | ``` 346 | Login Succeeded 347 | ``` 348 | 349 | *[Espaço para print: Login bem-sucedido no ECR]* 350 | 351 | ### Passo 5.3: Tagar a imagem para o ECR 352 | 353 | ```bash 354 | docker tag meu-website:v1.0 123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website:v1.0 355 | ``` 356 | 357 | ### Passo 5.4: Push da imagem 358 | 359 | ```bash 360 | docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website:v1.0 361 | ``` 362 | 363 | Você verá o progresso do upload: 364 | ``` 365 | The push refers to repository [123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website] 366 | abc123: Pushed 367 | def456: Pushed 368 | v1.0: digest: sha256:xyz789... size: 1234 369 | ``` 370 | 371 | *[Espaço para print: Push concluído]* 372 | 373 | ### Passo 5.5: Verificar no Console AWS 374 | 375 | 1. Volte ao ECR no console AWS 376 | 2. Clique no seu repositório 377 | 3. Você deve ver a imagem com a tag v1.0 378 | 379 | *[Espaço para print: Imagem no ECR]* 380 | 381 | --- 382 | 383 | ## 🖥️ Fase 6: Provisionamento da Instância EC2 384 | 385 | ### Passo 6.1: Navegar para EC2 386 | 387 | 1. No console AWS, busque por "EC2" 388 | 2. Clique em "EC2" 389 | 390 | ### Passo 6.2: Lançar instância 391 | 392 | 1. Clique em "Launch Instance" 393 | 2. Configure: 394 | 395 | #### Nome e tags 396 | - **Name**: `meu-website-server` 397 | 398 | #### Imagem de aplicação e sistema operacional 399 | - **AMI**: Amazon Linux 2023 (Free tier eligible) 400 | 401 | *[Espaço para print: Seleção da AMI]* 402 | 403 | #### Tipo de instância 404 | - **Instance type**: t2.micro (Free tier eligible) 405 | 406 | *[Espaço para print: Seleção do tipo de instância]* 407 | 408 | #### Par de chaves 409 | - Clique em "Create new key pair" 410 | - **Key pair name**: `meu-website-key` 411 | - **Key pair type**: RSA 412 | - **Private key file format**: .pem (Linux/Mac) ou .ppk (Windows/PuTTY) 413 | - Clique em "Create key pair" e salve o arquivo 414 | 415 | ⚠️ **IMPORTANTE**: Guarde este arquivo com segurança! Você precisará dele para acessar a EC2. 416 | 417 | *[Espaço para print: Criação do key pair]* 418 | 419 | #### Configurações de rede 420 | - **VPC**: Default 421 | - **Subnet**: No preference 422 | - **Auto-assign public IP**: Enable 423 | - **Firewall (security groups)**: Create security group 424 | - **Security group name**: `meu-website-sg` 425 | - **Description**: Security group for website 426 | 427 | #### Regras do Security Group 428 | Adicione as seguintes regras: 429 | 430 | | Type | Protocol | Port Range | Source | 431 | |------|----------|------------|--------| 432 | | SSH | TCP | 22 | My IP | 433 | | HTTP | TCP | 80 | 0.0.0.0/0 | 434 | 435 | *[Espaço para print: Configuração do Security Group]* 436 | 437 | #### Configurar armazenamento 438 | - **Volume**: 8 GiB gp3 (padrão) 439 | 440 | ### Passo 6.3: Configurar IAM Role (Permissões para ECR) 441 | 442 | #### Criar IAM Role 443 | 1. Em "Advanced details", encontre "IAM instance profile" 444 | 2. Clique em "Create new IAM profile" 445 | 3. Ou vá para IAM Console e: 446 | - Clique em "Roles" → "Create role" 447 | - **Trusted entity**: AWS service 448 | - **Use case**: EC2 449 | - **Permissions**: Adicione `AmazonEC2ContainerRegistryReadOnly` 450 | - **Role name**: `EC2-ECR-Role` 451 | 452 | *[Espaço para print: Criação do IAM Role]* 453 | 454 | 4. Volte para a configuração da EC2 e selecione o role criado 455 | 456 | ### Passo 6.4: Revisar e lançar 457 | 458 | 1. Revise todas as configurações 459 | 2. Clique em "Launch instance" 460 | 3. Aguarde a instância inicializar (status: running) 461 | 462 | *[Espaço para print: Instância EC2 rodando]* 463 | 464 | ### Passo 6.5: Anotar informações importantes 465 | 466 | Anote: 467 | - **Public IP**: Ex: 54.123.45.67 468 | - **Instance ID**: Ex: i-0abc123def456789 469 | 470 | --- 471 | 472 | ## 🚀 Fase 7: Deploy na EC2 473 | 474 | ### Passo 7.1: Conectar à instância EC2 475 | 476 | #### No Linux/Mac: 477 | ```bash 478 | # Ajustar permissões da chave 479 | chmod 400 meu-website-key.pem 480 | 481 | # Conectar via SSH 482 | ssh -i meu-website-key.pem ec2-user@54.123.45.67 483 | ``` 484 | 485 | #### No Windows (usando PuTTY): 486 | 1. Converta a chave .pem para .ppk usando PuTTYgen 487 | 2. Use PuTTY para conectar com a chave .ppk 488 | 489 | Você verá: 490 | ``` 491 | , #_ 492 | ~\_ ####_ Amazon Linux 2023 493 | ~~ \_#####\ 494 | ~~ \###| 495 | ~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023 496 | ~~ V~' '-> 497 | ~~~ / 498 | ~~._. _/ 499 | _/ _/ 500 | _/m/' 501 | [ec2-user@ip-172-31-xx-xx ~]$ 502 | ``` 503 | 504 | *[Espaço para print: Conexão SSH estabelecida]* 505 | 506 | ### Passo 7.2: Instalar Docker na EC2 507 | 508 | ```bash 509 | # Atualizar pacotes 510 | sudo yum update -y 511 | 512 | # Instalar Docker 513 | sudo yum install docker -y 514 | 515 | # Iniciar serviço Docker 516 | sudo systemctl start docker 517 | 518 | # Habilitar Docker no boot 519 | sudo systemctl enable docker 520 | 521 | # Adicionar ec2-user ao grupo docker 522 | sudo usermod -a -G docker ec2-user 523 | 524 | # Verificar instalação 525 | docker --version 526 | ``` 527 | 528 | ### Passo 7.3: Fazer logout e login novamente 529 | 530 | ```bash 531 | # Sair 532 | exit 533 | 534 | # Conectar novamente 535 | ssh -i meu-website-key.pem ec2-user@54.123.45.67 536 | ``` 537 | 538 | ### Passo 7.4: Autenticar Docker com ECR na EC2 539 | 540 | ```bash 541 | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com 542 | ``` 543 | 544 | *[Espaço para print: Login ECR na EC2]* 545 | 546 | ### Passo 7.5: Pull da imagem do ECR 547 | 548 | ```bash 549 | docker pull 123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website:v1.0 550 | ``` 551 | 552 | Você verá: 553 | ``` 554 | v1.0: Pulling from meu-website 555 | Status: Downloaded newer image for 123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website:v1.0 556 | ``` 557 | 558 | *[Espaço para print: Pull concluído]* 559 | 560 | ### Passo 7.6: Executar o container 561 | 562 | ```bash 563 | docker run -d -p 80:80 --name meu-website-prod --restart always 123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website:v1.0 564 | ``` 565 | 566 | #### 🎓 Parâmetros importantes: 567 | - **--restart always**: Reinicia o container se a EC2 reiniciar 568 | - **-p 80:80**: Mapeia porta 80 (padrão HTTP) 569 | 570 | ### Passo 7.7: Verificar se está rodando 571 | 572 | ```bash 573 | # Verificar container 574 | docker ps 575 | 576 | # Verificar logs 577 | docker logs meu-website-prod 578 | ``` 579 | 580 | *[Espaço para print: Container rodando na EC2]* 581 | 582 | --- 583 | 584 | ## ✅ Verificação e Testes 585 | 586 | ### Teste 1: Acessar pelo navegador 587 | 588 | 1. Abra seu navegador 589 | 2. Digite o IP público da EC2: `http://54.123.45.67` 590 | 3. Seu website deve aparecer! 🎉 591 | 592 | *[Espaço para print: Website funcionando na AWS]* 593 | 594 | ### Teste 2: Verificar logs na EC2 595 | 596 | ```bash 597 | # Logs do container 598 | docker logs -f meu-website-prod 599 | 600 | # Status do container 601 | docker stats meu-website-prod 602 | ``` 603 | 604 | ### Teste 3: Testar reinicialização 605 | 606 | ```bash 607 | # Parar o container 608 | docker stop meu-website-prod 609 | 610 | # Verificar se parou 611 | docker ps 612 | 613 | # Iniciar novamente 614 | docker start meu-website-prod 615 | 616 | # Verificar se voltou 617 | docker ps 618 | ``` 619 | 620 | --- 621 | 622 | ## 🔧 Troubleshooting 623 | 624 | ### Problema 1: "Cannot connect to the Docker daemon" 625 | 626 | **Solução**: 627 | ```bash 628 | sudo systemctl start docker 629 | sudo usermod -a -G docker $USER 630 | # Fazer logout e login novamente 631 | ``` 632 | 633 | ### Problema 2: Site não abre no navegador 634 | 635 | **Verificações**: 636 | 1. Security Group tem porta 80 aberta? 637 | 2. Container está rodando? (`docker ps`) 638 | 3. IP público está correto? 639 | 4. Teste com curl na EC2: `curl localhost` 640 | 641 | ### Problema 3: "No basic auth credentials" no pull do ECR 642 | 643 | **Solução**: 644 | ```bash 645 | # Re-autenticar 646 | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin [ECR_URI] 647 | ``` 648 | 649 | ### Problema 4: Permissão negada no Docker 650 | 651 | **Solução**: 652 | ```bash 653 | # Adicionar usuário ao grupo docker 654 | sudo usermod -a -G docker ec2-user 655 | # Logout e login 656 | exit 657 | ssh -i key.pem ec2-user@IP 658 | ``` 659 | 660 | --- 661 | 662 | ## 🧹 Limpeza de Recursos 663 | 664 | ⚠️ **IMPORTANTE**: Para evitar custos, limpe os recursos após o laboratório! 665 | 666 | ### Passo 1: Parar e remover container na EC2 667 | 668 | ```bash 669 | docker stop meu-website-prod 670 | docker rm meu-website-prod 671 | docker rmi 123456789012.dkr.ecr.us-east-1.amazonaws.com/meu-website:v1.0 672 | ``` 673 | 674 | ### Passo 2: Terminar instância EC2 675 | 676 | 1. Console AWS → EC2 677 | 2. Selecione sua instância 678 | 3. Actions → Instance State → Terminate 679 | 680 | *[Espaço para print: Confirmação de terminate]* 681 | 682 | ### Passo 3: Deletar imagem do ECR 683 | 684 | 1. Console AWS → ECR 685 | 2. Selecione o repositório 686 | 3. Selecione a imagem 687 | 4. Delete 688 | 689 | ### Passo 4: Deletar repositório ECR (opcional) 690 | 691 | 1. Selecione o repositório 692 | 2. Delete 693 | 694 | ### Passo 5: Deletar Security Group 695 | 696 | 1. EC2 → Security Groups 697 | 2. Selecione `meu-website-sg` 698 | 3. Actions → Delete 699 | 700 | ### Passo 6: Deletar IAM Role (opcional) 701 | 702 | 1. IAM → Roles 703 | 2. Selecione `EC2-ECR-Role` 704 | 3. Delete 705 | 706 | --- 707 | 708 | ## 🎓 Conceitos Aprendidos 709 | 710 | ✅ **Containerização**: Empacotamento de aplicações com suas dependências 711 | 712 | ✅ **Docker**: Plataforma para criar e executar containers 713 | 714 | ✅ **Dockerfile**: Arquivo de configuração para construir imagens 715 | 716 | ✅ **ECR**: Registro privado de imagens Docker na AWS 717 | 718 | ✅ **EC2**: Máquinas virtuais na nuvem AWS 719 | 720 | ✅ **Security Groups**: Firewall virtual para EC2 721 | 722 | ✅ **IAM Roles**: Gerenciamento de permissões na AWS 723 | 724 | --- 725 | 726 | ## 🚀 Próximos Passos 727 | 728 | Após completar este laboratório, você está pronto para: 729 | 730 | 1. **Projeto 2**: Automatizar este processo com CI/CD 731 | 2. **Projeto 3**: Usar Terraform para Infrastructure as Code 732 | 3. **Explorar**: Docker Compose, Kubernetes, ECS/Fargate 733 | 734 | --- 735 | 736 | ## 📚 Recursos Adicionais 737 | 738 | - [Documentação Docker](https://docs.docker.com/) 739 | - [AWS ECR Documentation](https://docs.aws.amazon.com/ecr/) 740 | - [AWS EC2 User Guide](https://docs.aws.amazon.com/ec2/) 741 | - [Best Practices for Dockerfile](https://docs.docker.com/develop/dev-best-practices/) 742 | 743 | --- 744 | 745 | ## 📝 Notas 746 | 747 | Use este espaço para suas anotações pessoais: 748 | 749 | ``` 750 | _____________________________________________________________ 751 | _____________________________________________________________ 752 | _____________________________________________________________ 753 | _____________________________________________________________ 754 | ``` 755 | 756 | --- 757 | 758 | **Parabéns! 🎉** Você completou o laboratório de containerização e deploy manual na AWS! 759 | 760 | Desenvolvido com ❤️ para a jornada DevOps --------------------------------------------------------------------------------