<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <docs>https://blogs.law.harvard.edu/tech/rss</docs>
    <title>Infraestrutura on FXShell - DevOps &amp; Sec</title>
    <link>https://fxshell.com.br/tags/infraestrutura/</link>
    <description>Recent content in Infraestrutura on FXShell - DevOps &amp; Sec</description>
    <image>
      <title>Infraestrutura on FXShell - DevOps &amp; Sec</title>
      <link>https://fxshell.com.br/tags/infraestrutura/</link>
      <url>fxshell.png</url>
    </image>
    <ttl>1440</ttl>
    <generator>Hugo 0.152.2</generator>
    <language>pt-br</language>
    <lastBuildDate>Thu, 14 May 2026 21:17:58 UT</lastBuildDate>
    <atom:link href="https://fxshell.com.br/tags/infraestrutura/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Ansible Lab: Provisionando Infraestrutura Web Segura do Zero</title>
      <link>https://fxshell.com.br/posts/ansible-lab-infra-segura/</link>
      <pubDate>Tue, 21 Apr 2026 13:00:00 UT</pubDate>
      <dc:creator>Felipe da Matta</dc:creator>
      <guid>https://fxshell.com.br/posts/ansible-lab-infra-segura/</guid>
      <description>Cenário: você tem 4 VMs vazias e precisa subir uma stack web completa — load balancer, dois servidores de aplicação, banco de dados, tudo com segurança configurada desde o início — em menos de 5 minutos. Só com Ansible.
Este post documenta um lab que montei para praticar exatamente isso: infraestrutura como código, do zero até uma stack funcional e segura, reproduzível com um único comando.
Objetivo do Lab O objetivo é simular, localmente, um ambiente que existe de verdade em qualquer empresa que tenha um sistema web em produção. Em vez de provisionar um servidor por vez — conectando via SSH, instalando pacotes na mão e torcendo para não esquecer nada — o lab demonstra como automatizar todo esse processo com Ansible.
</description>
      <content:encoded><![CDATA[Cenário: você tem 4 VMs vazias e precisa subir uma stack web completa — load balancer, dois servidores de aplicação, banco de dados, tudo com segurança configurada desde o início — em menos de 5 minutos. Só com Ansible.
Este post documenta um lab que montei para praticar exatamente isso: infraestrutura como código, do zero até uma stack funcional e segura, reproduzível com um único comando.
Objetivo do Lab O objetivo é simular, localmente, um ambiente que existe de verdade em qualquer empresa que tenha um sistema web em produção. Em vez de provisionar um servidor por vez — conectando via SSH, instalando pacotes na mão e torcendo para não esquecer nada — o lab demonstra como automatizar todo esse processo com Ansible.
Na prática, esse tipo de automação é usado para:
Subir novos ambientes (staging, produção, DR) de forma idêntica e rápida Garantir que todos os servidores estejam sempre na configuração correta, sem desvios Integrar o provisionamento em pipelines de CI/CD, onde um ambiente novo é criado automaticamente a cada release Padronizar configurações de segurança em toda a frota de servidores Tecnologias Utilizadas Antes de entrar no código, vale entender o papel de cada ferramenta.
Ansible é uma ferramenta de automação de infraestrutura. Você descreve o estado desejado dos seus servidores em arquivos YAML (os chamados playbooks e roles), e o Ansible se conecta via SSH e aplica essas configurações. Sem agente instalado nos servidores, sem banco de dados, sem daemon rodando — é simples por design.
Vagrant é uma ferramenta para criar e gerenciar máquinas virtuais de forma automatizada. Com um único arquivo de configuração (o Vagrantfile), você define quantas VMs quer, qual sistema operacional, qual IP de rede, quanta memória — e o Vagrant cria tudo isso para você. É amplamente usado para criar ambientes de desenvolvimento e laboratório locais, sem precisar pagar por cloud ou configurar VMs manualmente pelo VirtualBox.
VirtualBox é o software de virtualização que o Vagrant usa por baixo dos panos neste lab. É ele quem de fato cria e executa as máquinas virtuais. O Vagrant é a camada de abstração que automatiza a criação delas.
HAProxy é um load balancer de alto desempenho. Ele recebe as requisições dos usuários e as distribui entre os servidores de aplicação disponíveis. Se um servidor cair, o HAProxy para de mandar tráfego para ele automaticamente. É usado em praticamente toda arquitetura web que precisa de escalabilidade e alta disponibilidade.
Nginx é um servidor web e proxy reverso. Neste lab ele serve a aplicação nos dois web servers. No mercado é comum encontrá-lo tanto como servidor de aplicação quanto como proxy na frente de outros serviços.
PHP-FPM é o gerenciador de processos PHP. É ele que executa o código da aplicação e responde às requisições que chegam pelo Nginx.
MySQL é o banco de dados relacional da stack. Armazena os dados da aplicação.
UFW (Uncomplicated Firewall) é a interface de gerenciamento do firewall do Linux. Com ele definimos quais portas e IPs têm permissão de se comunicar com cada servidor. No lab, por exemplo, o MySQL só aceita conexões da rede interna — não há como acessá-lo de fora.
fail2ban monitora os logs do sistema e bane automaticamente IPs que apresentam comportamento suspeito — como várias tentativas de login SSH com falha em sequência. É uma camada de defesa simples e muito efetiva contra ataques de força bruta.
Arquitetura ┌─────────────────────────────────────────────────────────┐ │ ANSIBLE CONTROL NODE │ │ (seu terminal / CI/CD) │ └──────────────────────┬──────────────────────────────────┘ │ SSH (porta 22) ┌─────────────┼─────────────┐ ▼ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ lb-01 │ │ web-01 │ │ web-02 │ │ db-01 │ │ HAProxy │ │ Nginx │ │ Nginx │ │ MySQL │ │:80/:443 │ │ PHP-FPM │ │ PHP-FPM │ │ :3306 │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ Servidor Roles aplicadas lb-01 common, hardening, haproxy web-01 common, hardening, nginx, php web-02 common, hardening, nginx, php db-01 common, hardening, mysql Cada servidor recebe a role common (configurações base) e a role hardening (segurança), além das roles específicas do seu papel na stack.
Preparando o Ambiente com Vagrant O Vagrant cria as 4 VMs localmente com um único vagrant up. Cada máquina recebe um IP fixo na rede privada 192.168.56.0/24, o que permite que o Ansible se comunique com todas elas sem nenhuma configuração extra de rede.
Vagrant.configure(&#34;2&#34;) do |config| config.vm.box = &#34;debian/bookworm64&#34; nodes = { &#34;lb-01&#34; =&gt; &#34;192.168.56.10&#34;, &#34;web-01&#34; =&gt; &#34;192.168.56.11&#34;, &#34;web-02&#34; =&gt; &#34;192.168.56.12&#34;, &#34;db-01&#34; =&gt; &#34;192.168.56.13&#34; } nodes.each do |name, ip| config.vm.define name do |node| node.vm.hostname = name node.vm.network &#34;private_network&#34;, ip: ip node.vm.provider &#34;virtualbox&#34; do |vb| vb.memory = &#34;512&#34; vb.cpus = 1 end end end end vagrant up Quando as VMs estiverem rodando, o Ansible assume o controle.
Estrutura do Projeto O projeto segue a estrutura padrão de roles do Ansible. Cada role é um diretório independente com suas tasks, templates e variáveis. Essa separação facilita reutilizar as roles em outros projetos — a role de hardening, por exemplo, pode ser aplicada em qualquer servidor sem nenhuma modificação.
ansible-lab/ ├── ansible.cfg ├── inventory/ │ └── hosts.ini ├── playbook.yml └── roles/ ├── common/ │ └── tasks/main.yml ├── hardening/ │ ├── tasks/main.yml │ └── templates/ │ └── sshd_config.j2 ├── haproxy/ │ ├── tasks/main.yml │ └── templates/ │ └── haproxy.cfg.j2 ├── nginx/ │ └── tasks/main.yml ├── php/ │ └── tasks/main.yml └── mysql/ ├── tasks/main.yml └── vars/main.yml ansible.cfg O arquivo de configuração do Ansible define o comportamento padrão da ferramenta: onde está o inventário, qual usuário usar para se conectar, se deve escalar privilégios automaticamente, entre outros. Isso evita ter que repetir essas opções em todo comando que você rodar.
[defaults] inventory = inventory/hosts.ini remote_user = vagrant private_key_file = ~/.vagrant.d/insecure_private_key host_key_checking = False forks = 5 log_path = ansible.log [privilege_escalation] become = True become_method = sudo become_user = root become_ask_pass = False inventory/hosts.ini O inventário é onde você diz ao Ansible quais servidores existem e como agrupá-los. Grupos permitem aplicar roles e variáveis diferentes para cada tipo de servidor — tudo o que estiver em [webservers] recebe as configurações de web server, tudo em [database] recebe as de banco de dados, e assim por diante.
[loadbalancer] lb-01 ansible_host=192.168.56.10 [webservers] web-01 ansible_host=192.168.56.11 web-02 ansible_host=192.168.56.12 [database] db-01 ansible_host=192.168.56.13 [all:vars] ansible_python_interpreter=/usr/bin/python3 [webservers:vars] db_host=192.168.56.13 [loadbalancer:vars] web_backends=[&#34;192.168.56.11&#34;, &#34;192.168.56.12&#34;] As Roles common Responsável pelas configurações base que todo servidor precisa ter: pacotes essenciais e sincronização de hora via chrony. Simples, mas garante uma base consistente em todas as máquinas — sem isso, você pode ter servidores com versões diferentes de ferramentas ou relógios dessincronizados, o que causa problemas sutis difíceis de depurar.
# roles/common/tasks/main.yml --- - name: Atualizar cache do apt apt: update_cache: yes cache_valid_time: 3600 - name: Instalar pacotes base apt: name: - vim - curl - wget - htop - net-tools - chrony state: present - name: Garantir chrony rodando service: name: chrony state: started enabled: yes hardening Esta é a role mais importante do ponto de vista de segurança. Ela configura o firewall, restringe o acesso SSH e ativa o bloqueio automático de IPs suspeitos — aplicado em todos os servidores, sem exceção.
# roles/hardening/tasks/main.yml --- - name: Instalar ferramentas de segurança apt: name: - ufw - fail2ban - unattended-upgrades state: present - name: Configurar UFW - política padrão deny ufw: state: enabled policy: deny direction: incoming - name: Permitir SSH ufw: rule: allow port: &#34;22&#34; proto: tcp - name: Aplicar configurações de segurança no SSH template: src: sshd_config.j2 dest: /etc/ssh/sshd_config owner: root group: root mode: &#34;0600&#34; validate: /usr/sbin/sshd -t -f %s notify: Reiniciar SSH - name: Ativar fail2ban service: name: fail2ban state: started enabled: yes - name: Configurar atualizações automáticas de segurança copy: dest: /etc/apt/apt.conf.d/50unattended-upgrades content: | Unattended-Upgrade::Allowed-Origins { &#34;${distro_id}:${distro_codename}-security&#34;; }; Unattended-Upgrade::Automatic-Reboot &#34;false&#34;; O template do SSH — arquivos .j2 são templates Jinja2, que permitem usar variáveis e lógica dentro de arquivos de configuração — desabilita login por senha e acesso direto como root, dois dos vetores de ataque mais comuns em servidores expostos na internet.
{# roles/hardening/templates/sshd_config.j2 #} Port 22 Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key # Autenticação PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys # Restrições X11Forwarding no AllowTcpForwarding no MaxAuthTries 3 LoginGraceTime 30 ClientAliveInterval 300 ClientAliveCountMax 2 UsePAM yes PrintLastLog yes Com PasswordAuthentication no, ataques de força bruta por senha simplesmente não funcionam — o servidor nem aceita esse tipo de autenticação. O fail2ban complementa banindo automaticamente IPs que insistem em tentar.
haproxy O load balancer distribui o tráfego entre os dois web servers em round-robin — cada requisição vai alternadamente para web-01 e web-02 — e verifica a saúde de cada servidor antes de repassar requisições. Se um web server cair, o HAProxy detecta pelo health check e para de mandar tráfego para ele até que volte.
# roles/haproxy/tasks/main.yml --- - name: Instalar HAProxy apt: name: haproxy state: present - name: Permitir porta 80 no firewall ufw: rule: allow port: &#34;80&#34; proto: tcp - name: Configurar HAProxy template: src: haproxy.cfg.j2 dest: /etc/haproxy/haproxy.cfg validate: haproxy -c -f %s notify: Reiniciar HAProxy - name: Garantir HAProxy rodando service: name: haproxy state: started enabled: yes Note o validate na task de configuração: o Ansible só aplica o arquivo se o HAProxy confirmar que a sintaxe está correta. Isso evita derrubar o serviço por conta de um erro de configuração.
{# roles/haproxy/templates/haproxy.cfg.j2 #} global log /dev/log local0 chroot /var/lib/haproxy user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull timeout connect 5000ms timeout client 50000ms timeout server 50000ms frontend web_frontend bind *:80 default_backend web_backends backend web_backends balance roundrobin option httpchk GET /health {% for backend in web_backends %} server web-{{ loop.index }} {{ backend }}:80 check {% endfor %} nginx + php Os web servers aceitam conexões apenas do load balancer — qualquer acesso direto pela porta 80 de outro IP é bloqueado pelo UFW. Isso garante que todo tráfego passe obrigatoriamente pelo HAProxy, sem atalhos.
# roles/nginx/tasks/main.yml --- - name: Instalar Nginx apt: name: nginx state: present - name: Permitir porta 80 apenas do load balancer ufw: rule: allow src: &#34;192.168.56.10&#34; port: &#34;80&#34; proto: tcp - name: Criar endpoint de health check copy: dest: /var/www/html/health content: &#34;OK&#34; owner: www-data group: www-data - name: Criar página de identificação do servidor copy: dest: /var/www/html/index.html content: &#34;&lt;h1&gt;Servidor: {{ inventory_hostname }}&lt;/h1&gt;&#34; owner: www-data group: www-data - name: Garantir Nginx rodando service: name: nginx state: started enabled: yes mysql O MySQL é configurado para escutar apenas no IP interno e aceitar conexões somente da sub-rede 192.168.56.0/24. Usuário de aplicação criado com privilégios mínimos — sem acesso root, sem acesso de fora da rede interna.
# roles/mysql/tasks/main.yml --- - name: Instalar MySQL e dependências Python apt: name: - mysql-server - python3-mysqldb state: present - name: Garantir MySQL rodando service: name: mysql state: started enabled: yes - name: Criar banco de dados da aplicação mysql_db: name: &#34;{{ db_name }}&#34; state: present - name: Criar usuário com acesso restrito por IP mysql_user: name: &#34;{{ db_user }}&#34; password: &#34;{{ db_password }}&#34; priv: &#34;{{ db_name }}.*:ALL&#34; host: &#34;192.168.56.%&#34; state: present - name: Restringir MySQL ao IP interno lineinfile: path: /etc/mysql/mysql.conf.d/mysqld.cnf regexp: &#34;^bind-address&#34; line: &#34;bind-address = 192.168.56.13&#34; notify: Reiniciar MySQL - name: Liberar acesso ao MySQL apenas da rede interna ufw: rule: allow src: &#34;192.168.56.0/24&#34; port: &#34;3306&#34; proto: tcp A senha do banco nunca deve ir em texto plano no repositório. O ansible-vault criptografa valores sensíveis dentro dos arquivos YAML — você commita o arquivo normalmente, mas só quem tem a chave consegue descriptografar.
ansible-vault encrypt_string &#39;SuaSenha&#39; --name &#39;vault_db_password&#39; # roles/mysql/vars/main.yml --- db_name: appdb db_user: appuser db_password: &#34;{{ vault_db_password }}&#34; Playbook Principal O playbook é o arquivo que orquestra tudo — ele define qual conjunto de roles é aplicado em qual grupo de servidores, e em qual ordem. É o ponto de entrada da automação.
# playbook.yml --- - name: Provisionar Load Balancer hosts: loadbalancer roles: - common - hardening - haproxy - name: Provisionar Servidores Web hosts: webservers roles: - common - hardening - nginx - php - name: Provisionar Banco de Dados hosts: database roles: - common - hardening - mysql Executando Antes de rodar de verdade, vale sempre fazer um dry-run com --check --diff para visualizar exatamente o que seria alterado em cada servidor, sem modificar nada:
# Verificar conectividade com todos os nós ansible all -m ping # Dry run — simula a execução sem alterar nada ansible-playbook playbook.yml --check --diff # Execução real ansible-playbook playbook.yml Resultado esperado:
PLAY RECAP lb-01 : ok=14 changed=12 unreachable=0 failed=0 web-01 : ok=17 changed=15 unreachable=0 failed=0 web-02 : ok=17 changed=15 unreachable=0 failed=0 db-01 : ok=16 changed=14 unreachable=0 failed=0 Verificando a Stack # O load balancer deve alternar entre web-01 e web-02 for i in {1..6}; do curl -s http://192.168.56.10; echo; done # Servidor: web-01 # Servidor: web-02 # Servidor: web-01 # Servidor: web-02 # ... # Health check do HAProxy curl http://192.168.56.10/health # OK # Confirmar fail2ban ativo em todos os servidores ansible all -m shell -a &#34;fail2ban-client status&#34; # Confirmar firewall ativo ansible all -m shell -a &#34;ufw status verbose&#34; Idempotência Um conceito central no Ansible — e na automação de infraestrutura em geral — é a idempotência: a capacidade de executar a mesma operação várias vezes e sempre chegar ao mesmo resultado, sem efeitos colaterais.
Rode o playbook novamente sem ter alterado nada:
ansible-playbook playbook.yml PLAY RECAP lb-01 : ok=14 changed=0 unreachable=0 failed=0 web-01 : ok=17 changed=0 unreachable=0 failed=0 web-02 : ok=17 changed=0 unreachable=0 failed=0 db-01 : ok=16 changed=0 unreachable=0 failed=0 changed=0 em todos os servidores. Antes de executar qualquer task, o Ansible verifica se o recurso já está no estado desejado. Se o pacote já está instalado, não instala de novo. Se o arquivo de configuração já está correto, não sobrescreve. Isso significa que você pode rodar o mesmo playbook quantas vezes quiser — em manutenção, em auditoria, em CI/CD — sem risco de quebrar o ambiente.
Comandos Ad-hoc para o Dia a Dia Nem tudo precisa de um playbook. Para tarefas pontuais, o Ansible permite rodar comandos diretamente em um grupo de servidores sem precisar criar um arquivo YAML:
# Ver uso de memória em todos os servidores ansible all -m shell -a &#34;free -h&#34; # Reiniciar nginx nos web servers ansible webservers -m service -a &#34;name=nginx state=restarted&#34; # Coletar informações do sistema (distribuição, versão, etc.) ansible all -m setup -a &#34;filter=ansible_distribution*&#34; # Verificar quais portas estão abertas ansible all -m shell -a &#34;ss -tlnp&#34; Para Que Isso Serve no Mercado Este lab reproduz, em escala reduzida, um padrão que existe em praticamente qualquer empresa com infraestrutura web:
Times de DevOps/SRE usam automação como essa para garantir que todos os ambientes — desenvolvimento, homologação, produção — sejam idênticos. Um bug que aparece só em produção muitas vezes é causado por diferença de configuração entre ambientes. Com IaC, isso deixa de ser um problema.
Onboarding de novos servidores vira um processo de minutos. Quando um servidor novo entra na frota, o Ansible aplica toda a configuração padrão automaticamente — sem checklist manual, sem risco de esquecer um passo.
Auditorias de segurança ficam muito mais simples. Em vez de acessar cada servidor para verificar se as configurações de segurança estão corretas, você roda o playbook e o resultado mostra exatamente o que está diferente do esperado.
Resposta a incidentes ganha velocidade. Se um servidor fica comprometido e precisa ser reconstruído do zero, o processo inteiro leva minutos — não horas ou dias tentando lembrar como aquele servidor foi configurado originalmente.
Conclusão Em menos de 5 minutos e algumas dezenas de linhas de YAML, a stack está de pé:
Load Balancer com HAProxy, round-robin e health check automático 2 Web Servers com Nginx respondendo e identificando o host Banco de dados MySQL com acesso restrito à rede interna Segurança aplicada em todos: SSH por chave, firewall ativo, bloqueio de força bruta e atualizações automáticas O ponto mais importante desse tipo de lab não é a tecnologia em si — é o fato de que a infraestrutura vira código. Ela fica versionada, documentada, reproduzível em qualquer ambiente e auditável linha a linha.
O próximo passo natural é integrar esse playbook em um pipeline CI/CD (GitHub Actions ou GitLab CI) e adicionar testes de infraestrutura com Molecule + Testinfra.
Referências:
Documentação oficial do Ansible Ansible Galaxy CIS Benchmarks para Linux ]]></content:encoded>
    </item>
    <item>
      <title>Terraform AWS — Provisionando uma VPC Segura com ALB, EC2 e RDS</title>
      <link>https://fxshell.com.br/posts/terraform-aws-vpc/</link>
      <pubDate>Tue, 21 Apr 2026 00:00:00 UT</pubDate>
      <dc:creator>Felipe da Matta</dc:creator>
      <guid>https://fxshell.com.br/posts/terraform-aws-vpc/</guid>
      <description>Toda vez que um time precisa criar um novo ambiente — seja para testes, staging ou produção — o processo manual de clicar no console da AWS abre espaço para erros, inconsistências e ambientes que ninguém sabe exatamente como foram configurados. Infraestrutura como Código resolve isso: você escreve a infraestrutura em arquivos de texto, versiona no Git e aplica com um comando.
Neste lab, construo uma VPC completa na AWS usando Terraform, com balanceador de carga, servidores web em subnets privadas, banco de dados MySQL e state remoto no S3.
</description>
      <content:encoded><![CDATA[Toda vez que um time precisa criar um novo ambiente — seja para testes, staging ou produção — o processo manual de clicar no console da AWS abre espaço para erros, inconsistências e ambientes que ninguém sabe exatamente como foram configurados. Infraestrutura como Código resolve isso: você escreve a infraestrutura em arquivos de texto, versiona no Git e aplica com um comando.
Neste lab, construo uma VPC completa na AWS usando Terraform, com balanceador de carga, servidores web em subnets privadas, banco de dados MySQL e state remoto no S3.
Objetivo do Lab Provisionar, via Terraform, uma infraestrutura web segura na AWS contendo:
VPC com subnets públicas e privadas em duas zonas de disponibilidade Application Load Balancer nas subnets públicas Duas instâncias EC2 com Nginx nas subnets privadas RDS MySQL 8 em subnet privada, sem acesso público Bastion host para acesso SSH operacional NAT Gateway para que as instâncias privadas acessem a internet State remoto no S3 com lock via DynamoDB Tecnologias Utilizadas Terraform é uma ferramenta de infraestrutura como código criada pela HashiCorp. Você descreve os recursos que quer criar (VMs, redes, bancos de dados) em arquivos .tf e o Terraform se encarrega de criar, modificar ou destruir esses recursos na cloud. É amplamente usada em times de DevOps e SRE para gerenciar infraestrutura de forma consistente e reproduzível.
AWS VPC (Virtual Private Cloud) é uma rede virtual isolada dentro da AWS onde você controla o espaço de endereçamento IP, as rotas e as regras de acesso. Tudo que você cria na AWS precisa estar dentro de uma VPC.
Subnets públicas e privadas dividem a VPC em camadas. Recursos em subnets públicas têm IP público e acesso direto à internet via Internet Gateway. Recursos em subnets privadas ficam isolados da internet — só se comunicam com o mundo externo via NAT Gateway, sem exposição direta.
Application Load Balancer (ALB) distribui o tráfego HTTP/HTTPS entre as instâncias de destino. Fica nas subnets públicas e repassa as requisições para os servidores web nas subnets privadas, aplicando health checks automaticamente.
EC2 (Elastic Compute Cloud) são as máquinas virtuais da AWS. Neste lab uso instâncias t3.micro com Amazon Linux 2023 e Nginx.
RDS (Relational Database Service) é o serviço gerenciado de banco de dados da AWS. A AWS cuida de backups, patches e failover. Uso MySQL 8 em instância db.t3.micro isolada em subnet privada.
S3 backend armazena o terraform.tfstate — arquivo que registra o estado atual da infraestrutura — em um bucket S3 com criptografia ativada. O DynamoDB garante que dois operadores não apliquem mudanças ao mesmo tempo (locking).
Arquitetura INTERNET │ ▼ [Internet Gateway] │ ▼ ┌─────────────────────────────────────────────┐ │ VPC — 10.0.0.0/16 │ │ │ │ ┌── us-east-1a ──┐ ┌── us-east-1b ──┐ │ │ │ public subnet │ │ public subnet │ │ │ │ 10.0.1.0/24 │ │ 10.0.2.0/24 │ │ │ │ [bastion] │ │ [nat-gw] │ │ │ └────────────────┘ └────────────────┘ │ │ │ │ │ │ [Application Load Balancer] │ │ │ │ │ │ ┌── private ─────┐ ┌── private ─────┐ │ │ │ 10.0.10.0/24 │ │ 10.0.20.0/24 │ │ │ │ [web-01 EC2] │ │ [web-02 EC2] │ │ │ └────────────────┘ └────────────────┘ │ │ │ │ │ [RDS MySQL] │ │ 10.0.10.0/24 (private) │ └─────────────────────────────────────────────┘ │ [S3 — tfstate] Recurso Tipo Subnet Acesso Internet Gateway aws_internet_gateway — Internet ALB aws_lb Pública Internet → EC2 Bastion EC2 t3.nano Pública SSH operador NAT Gateway aws_nat_gateway Pública Saída privada web-01 / web-02 EC2 t3.micro Privada Via ALB RDS MySQL 8 db.t3.micro Privada Via EC2 S3 (tfstate) aws_s3_bucket — Terraform Estrutura dos Arquivos terraform-aws-vpc/ ├── main.tf ← provider, backend S3 ├── variables.tf ← todas as variáveis com descrição e validação ├── outputs.tf ← DNS do ALB, IPs, endpoint RDS ├── vpc.tf ← VPC, subnets, IGW, NAT, route tables ├── security_groups.tf ← SGs separados por recurso ├── ec2.tf ← instâncias web e bastion ├── alb.tf ← ALB, target group, listener, S3 de logs └── rds.tf ← RDS MySQL, subnet group Separar em arquivos por responsabilidade facilita a leitura e evita um main.tf com centenas de linhas.
Backend S3 — State Remoto O state do Terraform registra exatamente o que foi criado na AWS. Sem state remoto, cada pessoa da equipe teria seu próprio estado local — o que é um desastre em times. O backend S3 centraliza o state com criptografia e o DynamoDB evita que dois apply aconteçam ao mesmo tempo.
Antes de qualquer coisa, crie o bucket e a tabela DynamoDB (só precisa fazer uma vez):
aws s3api create-bucket \ --bucket fxshell-terraform-state \ --region us-east-1 aws s3api put-bucket-versioning \ --bucket fxshell-terraform-state \ --versioning-configuration Status=Enabled aws dynamodb create-table \ --table-name terraform-locks \ --attribute-definitions AttributeName=LockID,AttributeType=S \ --key-schema AttributeName=LockID,KeyType=HASH \ --billing-mode PAY_PER_REQUEST VPC — Rede e Roteamento A VPC cria o espaço de rede isolado. As subnets públicas têm rota para o Internet Gateway; as privadas têm rota para o NAT Gateway — assim o tráfego de saída das instâncias privadas passa pelo NAT sem expor as máquinas diretamente.
resource &#34;aws_vpc&#34; &#34;main&#34; { cidr_block = var.vpc_cidr enable_dns_hostnames = true enable_dns_support = true tags = { Name = &#34;${var.project_name}-vpc&#34; } } O enable_dns_hostnames = true é necessário para que o RDS receba um hostname DNS resolvível dentro da VPC.
Security Groups — Princípio do Menor Privilégio Cada recurso tem seu próprio Security Group com regras mínimas. O EC2 aceita HTTP apenas do ALB, não da internet. O RDS aceita MySQL apenas do EC2. O bastion aceita SSH apenas do IP configurado.
# EC2 só aceita tráfego do ALB ingress { description = &#34;HTTP do ALB&#34; from_port = 80 to_port = 80 protocol = &#34;tcp&#34; security_groups = [aws_security_group.alb.id] } # RDS só aceita do EC2 ingress { description = &#34;MySQL das EC2&#34; from_port = 3306 to_port = 3306 protocol = &#34;tcp&#34; security_groups = [aws_security_group.ec2.id] } Referenciar o ID de outro Security Group como origem (em vez de um CIDR) é mais seguro: se uma instância for substituída e ganhar novo IP, a regra continua válida.
EC2 — Instâncias com IMDSv2 As instâncias usam user_data para instalar e configurar o Nginx automaticamente na inicialização. O http_tokens = &quot;required&quot; força o uso do IMDSv2 — a versão mais segura do serviço de metadados das instâncias, que exige um token de sessão antes de responder.
metadata_options { http_tokens = &#34;required&#34; } ALB — Balanceamento com Health Check O ALB distribui requisições entre as instâncias usando o algoritmo Round Robin. O health check testa a rota / a cada 30 segundos: se uma instância não responder com HTTP 200 por 3 verificações consecutivas, ela é removida do pool até se recuperar.
health_check { healthy_threshold = 2 unhealthy_threshold = 3 interval = 30 path = &#34;/&#34; matcher = &#34;200&#34; } Executando Antes de aplicar, sempre revise o plan:
# Inicializa o provider e o backend terraform init # Mostra o que será criado — sem alterar nada terraform plan -out=tfplan # Aplica o plan aprovado terraform apply tfplan A senha do banco nunca deve estar no código. Passe via variável de ambiente:
export TF_VAR_db_password=&#34;sua-senha-segura&#34; terraform apply Após o apply, os outputs mostram os dados importantes:
terraform output alb_dns_name # DNS para acessar a aplicação terraform output bastion_public_ip # IP para SSH de manutenção terraform output rds_endpoint # Endpoint do banco (sensitive) Para Destruir o Lab terraform destroy O Terraform remove todos os recursos na ordem correta, respeitando as dependências.
Para Que Serve no Mercado Times de cloud usam esse padrão (VPC + ALB + EC2 + RDS em subnets privadas) como base para praticamente qualquer aplicação web na AWS. O que muda é o tamanho das instâncias, o número de AZs e os serviços adicionais.
Com Terraform, essa infraestrutura vira um módulo reutilizável. Um time pode criar um ambiente de staging idêntico ao de produção em minutos, com certeza de que as configurações são as mesmas — algo impossível de garantir clicando manualmente no console.
Conclusão Infraestrutura como código não é só sobre automação — é sobre confiança. Quando a infra está em arquivos .tf versionados no Git, qualquer pessoa do time pode entender o que existe, revisar mudanças em pull requests e reverter para um estado anterior se algo der errado. O terraform plan funciona como um diff da infraestrutura: você vê exatamente o que vai mudar antes de mudar.
Referências Terraform AWS Provider Docs AWS VPC User Guide Terraform Best Practices ]]></content:encoded>
    </item>
    <item>
      <title>Ansible</title>
      <link>https://fxshell.com.br/posts/ansible/</link>
      <pubDate>Tue, 30 Mar 2021 00:56:17 UT</pubDate>
      <dc:creator>Felipe da Matta</dc:creator>
      <guid>https://fxshell.com.br/posts/ansible/</guid>
      <description>O Ansible é uma ferramenta de automação de infraestrutura open source que permite gerenciar configurações, provisionar servidores e orquestrar tarefas complexas em dezenas ou centenas de máquinas ao mesmo tempo — tudo a partir de um único ponto de controle, sem instalar nenhum agente nos servidores alvo.
O nome vem da ficção científica: um &ldquo;ansible&rdquo; é um dispositivo de comunicação superlumínica que transmite informação instantaneamente para múltiplos destinos. A metáfora é precisa.
</description>
      <content:encoded><![CDATA[O Ansible é uma ferramenta de automação de infraestrutura open source que permite gerenciar configurações, provisionar servidores e orquestrar tarefas complexas em dezenas ou centenas de máquinas ao mesmo tempo — tudo a partir de um único ponto de controle, sem instalar nenhum agente nos servidores alvo.
O nome vem da ficção científica: um &ldquo;ansible&rdquo; é um dispositivo de comunicação superlumínica que transmite informação instantaneamente para múltiplos destinos. A metáfora é precisa.
Os quatro pilares do Ansible Gerenciamento de Mudança — O Ansible é idempotente: executa uma tarefa somente se for necessário. Se o estado desejado já existe, ele não faz nada. Isso permite rodar o mesmo playbook várias vezes sem efeitos colaterais.
Provisionamento — Instala pacotes, configura serviços, cria usuários, aplica permissões — prepara um servidor do zero para uma função específica.
Automação — Executa tarefas de forma ordenada, permite tomar decisões condicionais e encadear operações complexas com YAML simples.
Orquestração — Coordena múltiplos servidores e aplicações em sequência: atualiza o banco antes dos app servers, drena o load balancer antes de reiniciar um nó.
Por que o Ansible? Sem agente. Não há software para instalar nos servidores gerenciados. O Ansible usa SSH (Linux) e WinRM (Windows) — protocolos que já existem em qualquer servidor.
YAML simples. Os playbooks são legíveis por qualquer pessoa da equipe — dev, ops ou gerência. Não é uma DSL exótica, é YAML com lógica.
Configuração rápida. Sem daemon, sem banco de dados, sem porta extra. Instale o Ansible no control node e comece a usar.
Seguro. SSH é o canal de comunicação. Suporte nativo a chaves SSH, LDAP e Kerberos para autenticação.
Arquitetura O Control Node é a única máquina com Ansible instalado. A partir dele, o Ansible se conecta via SSH aos hosts Linux e via WinRM aos hosts Windows, empurra os módulos Python temporariamente, executa as tarefas e remove tudo ao final. Nenhum rastro fica nos hosts gerenciados.
Como funciona O Ansible é desenvolvido em Python e requer Python ≥ 2.7 ou ≥ 3.5. Ele sempre busca o interpretador em /usr/bin/python por padrão — isso pode ser ajustado com a variável ansible_python_interpreter.
A comunicação acontece via:
SSH para servidores Linux (usuário + senha ou chave SSH) WinRM para servidores Windows A autenticação é descentralizada — pode ser feita com LDAP ou Kerberos para ambientes corporativos.
Fluxo de execução de um Playbook Ao executar ansible-playbook site.yml -i hosts, o Ansible:
Lê o playbook YAML e interpreta as plays Consulta o inventário para descobrir quais hosts executam cada play Determina quais módulos precisam ser executados (apt, copy, service, template&hellip;) Conecta via SSH/WinRM nos hosts alvos Aplica cada task, reporta o estado (ok / changed / failed) e aciona handlers se necessário Instalação O Ansible não adiciona banco de dados, daemon ou software persistente nos hosts. A única dependência é Python.
RHEL / CentOS / Fedora — habilite o EPEL antes:
sudo yum install ansible Ubuntu / Debian:
sudo apt-add-repository ppa:ansible/ansible sudo apt-get update sudo apt-get install ansible Via pip (qualquer distro):
sudo apt-get install python3-pip # se não tiver pip sudo pip3 install ansible sudo pip3 install ansible --upgrade # para atualizar Após instalar, configure o acesso SSH:
ssh-keygen -t rsa # gere sua chave ssh-copy-id user@host # copie para os hosts Configuração — ansible.cfg O arquivo principal de configuração é o ansible.cfg. A ordem de leitura (da menor para a maior precedência):
/etc/ansible/ansible.cfg (global) ~/.ansible.cfg (usuário) ./ansible.cfg (diretório corrente) Variável de ambiente ANSIBLE_CONFIG Um ansible.cfg funcional e comentado:
[defaults] # Execução paralela em até 5 hosts simultaneamente forks = 5 log_path = /var/log/ansible.log module_name = command executable = /bin/bash # Caminhos inventory = /etc/ansible/hosts roles_path = /etc/ansible/roles remote_tmp = ~/.ansible/tmp local_tmp = ~/.ansible/tmp # Autenticação remote_user = root ask_pass = no # SSH remote_port = 22 timeout = 10 host_key_checking = False private_key_file = ~/.ssh/id_rsa [privilege_escalation] become = True become_method = sudo become_user = root become_ask_pass = False [ssh_connection] scp_if_ssh = smart transfer_method = smart retries = 3 Inventário — Hosts, Grupos e Sub-grupos O inventário define quais servidores o Ansible conhece e como eles se organizam. Pode ser um arquivo estático (/etc/ansible/hosts) ou dinâmico (script que consulta cloud providers).
Hosts individuais:
192.168.1.151 192.168.1.234 Grupos:
[servidores_bd] 192.168.1.151 [servidores_web] 192.168.1.234 Sub-grupos (children):
[servidores:children] servidores_web servidores_bd Variáveis por grupo:
[servidores_bd:vars] ansible_ssh_port=22 ansible_ssh_user=osboxes ansible_ssh_pass=osboxes.org ansible_become=yes ansible_become_method=sudo Alias por host:
mysql ansible_ssh_host=192.168.1.234 Comandos Ad-hoc Ad-hoc são comandos pontuais executados sem playbook — ideais para operações rápidas.
Sintaxe base:
ansible &lt;hosts&gt; -u &lt;user&gt; -k [-b] -m &lt;módulo&gt; -a &#34;&lt;args&gt;&#34; Flags:
Flag Função -u usuário remoto -k solicita senha SSH -K solicita senha para sudo -b executa com elevação (become) -m módulo a usar -a argumento do módulo -i inventário alternativo Ping em todos os hosts:
ansible all -m ping -u osboxes -k 192.168.1.151 | SUCCESS =&gt; { &#34;changed&#34;: false, &#34;ping&#34;: &#34;pong&#34; } 192.168.1.234 | SUCCESS =&gt; { &#34;changed&#34;: false, &#34;ping&#34;: &#34;pong&#34; } Coletar facts do sistema:
ansible 192.168.1.234 -u osboxes -k -m setup Reiniciar serviço SSH:
ansible 192.168.1.151 -u osboxes -k -b -m systemd -a &#34;name=ssh state=restarted&#34; Executar comando shell:
ansible 192.168.1.151 -u osboxes -k -b -m shell -a &#34;systemctl status ssh&#34; Comando direto (módulo command por padrão):
ansible 192.168.1.151 -u osboxes -k -a &#34;pwd&#34; Filtrar por grupo:
ansible -i hosts servidores_bd -m ping -u osboxes -k Para ignorar o aviso de Python legado, adicione ao ansible.cfg:
interpreter_python = auto_legacy_silent Roles — Automação Modular e Reutilizável Roles são a forma correta de organizar automação complexa. Em vez de um playbook gigante, você cria unidades independentes e reutilizáveis — uma role para nginx, outra para mysql, outra para hardening — e as compõe no playbook principal.
Estrutura de diretórios padrão:
playbook.yml └── roles/ └── nginx/ ├── tasks/ │ └── main.yml # lista de tarefas (obrigatório) ├── handlers/ │ └── main.yml # acionados por notify nas tasks ├── templates/ │ └── nginx.conf.j2 # Jinja2 com variáveis dinâmicas ├── files/ # arquivos estáticos para cópia ├── vars/ │ └── main.yml # variáveis com prioridade alta ├── defaults/ │ └── main.yml # defaults facilmente sobrescritíveis └── meta/ └── main.yml # dependências entre roles (lido primeiro) Chamando roles no playbook:
--- - hosts: webserver roles: - common # executada primeiro - nginx - php - mysql A execução de uma role é definida pelas tasks em tasks/main.yml. O diretório meta é analisado primeiro para resolver dependências.
Variáveis e Facts As variáveis permitem que o mesmo playbook funcione de forma diferente em cada host ou ambiente.
Ordem de prioridade (menor → maior):
1. role/defaults/main.yml ← mais fácil de sobrescrever 2. inventory file vars 3. group_vars/all 4. group_vars/* 5. host_vars/* 6. host facts (módulo setup) 7. role/vars/main.yml 8. set_fact / registered vars 9. extra vars (-e) ← prioridade máxima Ansible Facts — o módulo setup descobre automaticamente informações de cada host:
ansible hostname -m setup Retorna sistema operacional, IPs, memória, CPUs, discos, variáveis de ambiente e muito mais. Essas informações ficam disponíveis como variáveis nos playbooks: {{ ansible_os_family }}, {{ ansible_default_ipv4.address }}, etc.
Exemplo de estrutura com group_vars:
├── group_vars/ │ └── servidores ← variáveis aplicadas ao grupo ├── hosts ├── host_vars/ └── roles/ Usar variável extra na linha de comando (maior prioridade):
ansible-playbook site.yml -e &#34;nginx_port=8080&#34; Próximos passos Com esse conhecimento base, você está pronto para:
Criar playbooks completos que provisionam stacks inteiras Organizar infraestrutura com roles reutilizáveis (inclusive via Ansible Galaxy) Integrar Ansible em pipelines CI/CD (GitHub Actions, GitLab CI, Jenkins) Gerenciar secrets com Ansible Vault Escalar para centenas de servidores com inventários dinâmicos (AWS, Azure, GCP) Veja os posts relacionados para laboratórios práticos com Ansible em ação:
]]></content:encoded>
    </item>
    <item>
      <title>Docker</title>
      <link>https://fxshell.com.br/posts/docker/</link>
      <pubDate>Thu, 08 Oct 2020 14:10:44 UT</pubDate>
      <dc:creator>Felipe da Matta</dc:creator>
      <guid>https://fxshell.com.br/posts/docker/</guid>
      <description>Docker é a plataforma de containers mais usada no mercado. Com ela você empacota uma aplicação e todas as suas dependências em uma unidade portátil que roda de forma idêntica em qualquer ambiente — do laptop do dev até a produção em cloud.
O conceito central é isolamento: cada container roda de forma completamente isolada dos demais e do host, usando recursos do próprio kernel Linux.
Dois tipos de isolamento Lógico — Namespaces: isolam processos, redes, usuários e sistemas de arquivos. Cada container enxerga apenas o que é seu.
</description>
      <content:encoded><![CDATA[Docker é a plataforma de containers mais usada no mercado. Com ela você empacota uma aplicação e todas as suas dependências em uma unidade portátil que roda de forma idêntica em qualquer ambiente — do laptop do dev até a produção em cloud.
O conceito central é isolamento: cada container roda de forma completamente isolada dos demais e do host, usando recursos do próprio kernel Linux.
Dois tipos de isolamento Lógico — Namespaces: isolam processos, redes, usuários e sistemas de arquivos. Cada container enxerga apenas o que é seu.
Físico — Cgroups: limitam o uso de CPU, memória e disco. Garantem que um container não consuma recursos dos outros.
Arquitetura O Docker Engine usa três módulos do kernel Linux:
Namespaces — isolamento lógico de processos, redes, usuários Cgroups — isolamento físico de CPU, memória, I/O Netfilter — roteamento de rede, NAT e redirecionamento de pacotes Imagens em camadas: todas as camadas são read-only, exceto a camada superior de cada container (onde as alterações acontecem). Se você tem 5 containers baseados na mesma imagem de 500 MB, o disco não aloca 2,5 GB — todos compartilham a mesma base. Só a camada de escrita de cada container é individual.
Instalação curl -fsSL https://get.docker.com/ | bash docker version docker container ls Para usar sem sudo, adicione seu usuário ao grupo docker:
sudo usermod -aG docker $USER Ciclo de Vida do Container Rodando o primeiro container docker container run hello-world Flags essenciais do run Flag Função -d Daemon — roda em background -ti Terminal interativo (bash, sh) -p 8080:80 Mapeia porta do host para o container -m 128M Limita memória --cpus 0.5 Limita a 50% de um núcleo --name Define nome do container --rm Remove o container ao encerrar Containers interativos # Entrar dentro de um ubuntu docker container run -ti ubuntu # Ver processos (apenas os do container) root@2fd8c26be92e:/# ps -ef UID PID CMD root 1 /bin/bash root 8 ps -ef CTRL+D encerra o container (mata o processo principal). CTRL+P+Q sai sem matar o container.
Containers em background (daemon) Para serviços como nginx, nunca use -ti — o entrypoint não é o bash:
docker container run -d nginx Para executar comandos dentro de um container em execução, use exec:
docker container exec -ti &lt;id&gt; bash docker container exec -ti &lt;id&gt; ls /etc/nginx Gerenciamento docker container ls # containers em execução docker container ls -a # todos (incluindo parados) docker container stop &lt;id&gt; docker container start &lt;id&gt; docker container restart &lt;id&gt; docker container pause &lt;id&gt; docker container unpause &lt;id&gt; docker container rm &lt;id&gt; # remove parado docker container rm -f &lt;id&gt; # força remoção docker container logs -f &lt;id&gt; # logs em tempo real docker container inspect &lt;id&gt; # detalhes completos em JSON docker container stats &lt;id&gt; # uso de CPU/memória em tempo real docker container top &lt;id&gt; # processos rodando no container Limitando Recursos Definir limites na criação:
docker container run -d -m 128M --cpus 0.5 nginx Atualizar em container já em execução:
docker container update --cpus 0.8 --memory 64M &lt;id&gt; Testar pressão com stress (instalar dentro do container):
apt-get install -y stress stress --cpu 1 --vm-bytes 128M --vm 1 Volumes — Persistindo Dados O filesystem do container é volátil — quando o container é removido, tudo dentro dele some. Volumes existem fora do container e persistem independentemente.
Bind Mount — você define o caminho # Montar diretório do host no container docker container run -ti \ --mount type=bind,src=https://fxshell.com.br/opt/meuapp,dst=/app \ debian # Somente leitura docker container run -ti \ --mount type=bind,src=https://fxshell.com.br/opt/meuapp,dst=/app,ro \ debian Docker Volume — gerenciado pelo Docker # Criar volume docker volume create dbdados # Usar volume no container docker container run -d \ --mount type=volume,src=dbdados,dst=/data \ postgres:16 # Listar volumes docker volume ls # Inspecionar docker volume inspect dbdados # Remover (só se não estiver em uso) docker volume rm dbdados # Remover todos os volumes não utilizados docker volume prune Todos os volumes ficam em /var/lib/docker/volumes/.
Compartilhando volume entre containers docker container run -d -p 5432:5432 --name pgsql1 \ --mount type=volume,src=dbdados,dst=/data \ postgres:16 docker container run -d -p 5433:5432 --name pgsql2 \ --mount type=volume,src=dbdados,dst=/data \ postgres:16 Ambos os containers leem e escrevem no mesmo volume.
Backup de volume mkdir /opt/backup docker container run --rm \ --mount type=volume,src=dbdados,dst=/data \ --mount type=bind,src=https://fxshell.com.br/opt/backup,dst=/backup \ debian tar -cvf /backup/bkp-banco.tar /data Dockerfile — Criando Suas Imagens O Dockerfile descreve como construir uma imagem. Cada instrução cria uma nova camada.
Instruções principais Instrução Descrição FROM Imagem base — sempre a primeira linha RUN Executa comando no build, cria camada CMD Comando padrão ao iniciar o container ENTRYPOINT Executável principal do container COPY Copia arquivos para o filesystem ADD Como COPY, mas aceita TAR e URLs ENV Define variáveis de ambiente EXPOSE Documenta a porta que o container escuta VOLUME Declara ponto de montagem de volume WORKDIR Define diretório de trabalho USER Define usuário (padrão: root) LABEL Adiciona metadados à imagem ARG Variável de build-time (não fica na imagem) Exemplo: container com stress FROM debian LABEL app=&#34;stress-test&#34; ENV AMBIENTE=&#34;dev&#34; RUN apt-get update &amp;&amp; apt-get install -y stress &amp;&amp; apt-get clean CMD stress --cpu 1 --vm-bytes 64M --vm 1 docker image build -t meu-stress:1.0 . docker container run -d meu-stress:1.0 Exemplo: Apache com ENTRYPOINT FROM debian RUN apt-get update &amp;&amp; apt-get install -y apache2 &amp;&amp; apt-get clean ENV APACHE_LOCK_DIR=&#34;/var/lock&#34; ENV APACHE_PID_FILE=&#34;/var/run/apache2/apache2.pid&#34; ENV APACHE_RUN_USER=&#34;www-data&#34; ENV APACHE_RUN_GROUP=&#34;www-data&#34; ENV APACHE_LOG_DIR=&#34;/var/log/apache2&#34; LABEL description=&#34;Webserver&#34; version=&#34;1.0.0&#34; VOLUME /var/www/html/ EXPOSE 80 ENTRYPOINT [&#34;/usr/sbin/apachectl&#34;] CMD [&#34;-D&#34;, &#34;FOREGROUND&#34;] Multi-stage build — imagem final mínima Compila em uma imagem pesada, copia apenas o binário para uma imagem leve:
# Stage 1: build FROM golang AS build WORKDIR /src ADD . /src RUN go build -o goapp # Stage 2: imagem final FROM alpine:3.19 WORKDIR /app COPY --from=build /src/goapp /app ENTRYPOINT [&#34;./goapp&#34;] A imagem final tem apenas o binário + Alpine (~5 MB), sem o toolchain Go.
Buildar e publicar # Build local docker image build -t minha-imagem:1.0 . # Ver camadas e histórico docker history minha-imagem:1.0 # Login no Docker Hub docker login # Push docker image tag minha-imagem:1.0 usuario/minha-imagem:1.0 docker push usuario/minha-imagem:1.0 Registry Local Para manter suas imagens em ambiente privado sem depender do Docker Hub:
# Subir um registry local na porta 5000 docker container run -d \ -p 5000:5000 \ --restart=always \ --name registry \ registry:2 # Taguear imagem para o registry local docker tag minha-imagem:1.0 localhost:5000/minha-imagem:1.0 # Push para o registry local docker push localhost:5000/minha-imagem:1.0 Imagens ficam em /var/lib/registry/docker/registry/v2/repositories/.
Docker Swarm — Orquestração em Cluster O Swarm transforma múltiplos hosts Docker em um cluster com load balancing e failover automáticos.
Manager — conhece o estado do cluster, agenda containers, expõe a API.
Worker — executa os containers distribuídos pelo manager.
Criando o cluster # No host manager (gera um token) docker swarm init # Nos hosts workers (usar o token gerado) docker swarm join --token &lt;token&gt; &lt;manager-ip&gt;:2377 # Ver todos os nodes docker node ls Gerenciando nodes # Ver token para adicionar workers docker swarm join-token worker # Ver token para adicionar managers docker swarm join-token manager # Promover worker a manager docker node promote fxshell-02 # Rebaixar manager a worker docker node demote fxshell-02 # Pausar node (não recebe novos containers) docker node update --availability pause fxshell-02 # Dreno para manutenção (migra containers para outros nodes) docker node update --availability drain fxshell-02 # Reativar node docker node update --availability active fxshell-02 # Remover node do cluster docker swarm leave # rodar no próprio node docker node rm fxshell-02 # rodar no manager Services — o coração do Swarm Um Service define quantas réplicas de um container devem rodar, em quais ports e com quais configs. O Swarm distribui as réplicas pelos workers e garante que o número desejado esteja sempre disponível.
# Criar service com 5 réplicas de nginx docker service create \ --name webserver \ --replicas 5 \ -p 8080:80 \ nginx # Listar services docker service ls # Ver em quais nodes estão rodando docker service ps webserver # Detalhes completos docker service inspect webserver # Escalar para 10 réplicas docker service scale webserver=10 # Logs de todos os containers do service docker service logs -f webserver # Remover service docker service rm webserver Service com volume docker service create \ --name webserver \ --replicas 5 \ -p 8080:80 \ --mount type=volume,src=dados,dst=/app \ nginx O volume dados fica disponível em todos os containers do service, em todos os nodes.
Limpeza # Remover containers parados docker container prune # Remover volumes não utilizados docker volume prune # Remover imagens não utilizadas docker image prune # Limpeza completa (containers, imagens, redes, cache de build) docker system prune -a Referência rápida # Containers docker container run -d -p 8080:80 --name web nginx docker container exec -ti &lt;id&gt; bash docker container logs -f &lt;id&gt; docker container stats docker container inspect &lt;id&gt; # Imagens docker image ls docker image pull ubuntu:22.04 docker image build -t app:1.0 . docker image push usuario/app:1.0 docker image rm &lt;id&gt; # Volumes docker volume create dados docker volume ls docker volume inspect dados docker volume rm dados # Swarm docker swarm init docker node ls docker service create --name app --replicas 3 -p 80:80 nginx docker service scale app=5 docker service ps app ]]></content:encoded>
    </item>
  </channel>
</rss>
