DevOps Mind
Docker: o que é e como ele otimizou meu pipeline em fintech
Por muito tempo, o meu “deploy” foi subir código direto numa EC2, na mão. Sem container, sem pipeline: era puxar o código no servidor, reiniciar o serviço e torcer. Funcionava até o dia em que não funcionava: ambiente de homologação diferente do de produção, dependência que existia na minha máquina e não no servidor, e aquele clássico “na minha máquina roda”. Em ambiente financeiro, onde um deploy torto derruba pagamento, esse jeito manual e mal otimizado era uma bomba-relógio.
Foi o Docker que mudou essa conversa. Comecei a usar ainda no mundo telecom e já vi resultado, mas o estalo de verdade, entender o poder real da coisa, veio no mutirão DevOps do LINUXtips. Ali caiu a ficha: o container não é só “empacotar app”, é o que destrava um pipeline previsível de ponta a ponta. Neste post eu explico o que é Docker partindo desse ângulo, o de quem usa para acelerar entrega em produção, e mostro as pegadinhas que aprendi apanhando.
O que é Docker, em uma linha honesta
Docker é a ferramenta que empacota a sua aplicação junto com tudo que ela precisa para rodar (código, runtime, bibliotecas, configs) numa unidade isolada e portátil chamada container. A promessa concreta: a imagem que você testou no seu notebook é bit a bit a mesma que roda em homologação e em produção. Aquele “na minha máquina funciona” morre aqui, porque a máquina passa a ser a imagem.
Não confunda com máquina virtual. A VM virtualiza um sistema operacional inteiro (kernel próprio, gigabytes, minutos para subir). O container compartilha o kernel do host e isola só o que a aplicação enxerga, então sobe em segundos e pesa uma fração. Para um pipeline, essa diferença é tudo: build rápido, deploy rápido, rollback rápido.
Onde o Docker entrou no meu pipeline
Trocar o deploy manual na EC2 por um fluxo com container arrumou a casa em três pontos:
- Paridade de ambiente. A mesma imagem sobe em dev, homolog e prod. Sumiu a categoria inteira de bug “só acontece em produção”.
- Build versionado e auditável. Cada commit gera uma imagem com tag, guardada no registry. Se deu ruim, eu sei exatamente qual artefato subiu e volto para o anterior.
- Deploy previsível. Em vez de comandos manuais no servidor, o pipeline publica a imagem e o orquestrador cuida do resto.
Hoje o fluxo é: o Bitbucket Pipelines builda a imagem a cada push, envia para o AWS ECR (o registry privado da AWS) e o deploy puxa dessa imagem no cluster. O que antes era um ritual manual e arriscado virou um passo automatizado e repetível.
Dockerfile: a receita da imagem
O Dockerfile é o arquivo que descreve, passo a passo, como a imagem é montada. Um exemplo simples para uma aplicação PHP:
FROM php:8.2-fpm
RUN apt-get update && apt-get install -y libpq-dev \
&& docker-php-ext-install pdo pdo_pgsql
COPY . /var/www/app
WORKDIR /var/www/app
CMD ["php-fpm"]Funciona, mas carrega junto o compilador, headers e cache de pacote que só serviram para o build. Numa aplicação PHP real de pagamento, uma imagem assim ficava na casa dos 450 a 500 MB para mim. Imagem gorda é build lento, pull lento no cluster e mais superfície de ataque, o que num ambiente PCI ninguém quer.
Multistage build: a virada que enxugou a imagem
O multistage separa a etapa de construir da etapa de rodar. Você usa uma imagem “cheia” para compilar e instalar dependências, e copia só o resultado para uma imagem final enxuta:
# Stage 1: build (tem composer, ferramentas de compilação)
FROM composer:2 AS build
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-scripts
COPY . .
# Stage 2: runtime (só o necessário para rodar)
FROM php:8.2-fpm-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /var/www/app
COPY --from=build --chown=app:app /app /var/www/app
USER app
CMD ["php-fpm"]Naquela mesma aplicação PHP, o multistage me levou de ~480 MB para algo em torno de 110 a 130 MB (número aproximado, varia com as extensões). Menos peso significou pull mais rápido nos nós e menos coisa para um atacante explorar. É a diferença entre carregar a oficina inteira e carregar só a ferramenta que você vai usar.
A pegadinha que a documentação não grita: não rode como root
Por padrão, o processo dentro do container roda como root. Parece detalhe, mas é um risco de segurança sério: se alguém escapa do container, escapa como root. Eu já subi imagem rodando como root sem perceber, e a correção é simples e obrigatória: criar um usuário e grupo específicos e trocar para ele antes do CMD, como no exemplo acima (addgroup, adduser, USER app). Num ambiente que passa por auditoria PCI, isso não é “boa prática opcional”, é item de checklist.
Docker Compose: onde ainda faz sentido para mim
O Docker Compose orquestra vários containers com um único arquivo docker-compose.yml. Minha regra prática, depois de rodar isso em produção: Compose fica no local (desenvolvimento) e em EC2 de serviço, tipo um Zabbix que sobe com banco e app juntos. Para as aplicações que precisam escalar e se curar sozinhas, o lugar é o Kubernetes, não o Compose. Compose é o canivete do dia a dia; Kubernetes é a linha de produção.
services:
zabbix-server:
image: zabbix/zabbix-server-pgsql:latest
depends_on: [postgres]
postgres:
image: postgres:16
environment:
POSTGRES_DB: zabbixPor que virou padrão em fintech (e em quase todo lugar)
Juntando as peças: paridade de ambiente elimina bug de “só em prod”, imagens enxutas via multistage aceleram o pipeline e reduzem risco, o registry (ECR) versiona os artefatos e o pipeline (Bitbucket) automatiza o que era manual. Não é hype: é o que torna possível fazer deploy com frequência sem transformar cada subida num evento de risco. Para quem opera pagamento, previsibilidade vale mais que qualquer coisa, e é exatamente isso que o container entrega.
Se você ainda faz deploy na mão numa EC2, como eu fazia, o primeiro passo não é aprender Kubernetes: é containerizar uma aplicação, colocar num Dockerfile multistage, subir a imagem para um registry e automatizar o build. O resto do caminho fica muito mais curto depois disso.








