Imgproxy em Docker: URLs Assinadas e Otimização AVIF em Tempo Real
O Problema das Miniaturas Tradicionais: O Disco Fica Cheio Depressa
Em quase todas as plataformas de comércio eletrónico e portais de conteúdos, as imagens representam mais de 70% de todo o tráfego transferido. Os utilizadores e gestores de loja carregam fotos de 12 megapixels tiradas com telemóveis diretamente para o painel de controlo, esperando que o site mostre miniaturas nítidas e leves em computadores, tablets e smartphones.
Tradicionalmente, os programadores tentavam resolver isto gerando miniaturas no momento do carregamento: um script em Node.js ou PHP criava seis ou oito variações estáticas (foto_150x150.jpg, foto_600x400.jpg, foto_1200x800.jpg, e versões em WebP).
Este método tem problemas sérios:
- Desperdício Gigantesco de Armazenamento: Se tiveres 20.000 fotos de produtos, passas a ter mais de 200.000 ficheiros no disco, esgotando os inodes do Linux e tornando as cópias de segurança extremamente lentas.
- Falta de Flexibilidade de Design: Se o designer alterar as caixas dos produtos de 250px para 280px de largura, tens de criar um script para reprocessar a biblioteca inteira durante horas a fio.
- Formatos Ultrapassados: Se quiseres adotar codecs mais modernos como o AVIF, tens de voltar a converter todo o histórico.
A solução profissional é adotar a transformação de media a pedido (on-the-fly). Guardas apenas o ficheiro original em alta resolução, e um motor dedicado—o Imgproxy—redimensiona, corta e converte a imagem exatamente para as dimensões e para o formato que o ecrã do teu visitante necessita.
PIPELINE DE MEDIA EM TEMPO REAL COM IMGPROXY
- Pedido do Browser: /insecure/resize:fill:400:300/plain/local:///foto.jpg@avif
- Proxy Nginx / Cache de Borda (Cloudflare)
- Verifica a Cache: se já existir, devolve o AVIF em 2ms!
- Se não existir: passa o pedido ao contentor do Imgproxy
- Contentor Imgproxy (Go + libvips em Docker)
- Lê a imagem original do disco ou armazenamento S3
- Aplica corte e redimensionamento por hardware (libvips)
- Codifica para AVIF ou WebP em ~25 milissegundos
- Define Cache-Control: public, max-age=31536000, immutable
Esta arquitetura moderna é a base com que construímos websites de alta performance, garantindo que as tuas páginas abrem instantaneamente em qualquer dispositivo móvel.
Como Instalar o Imgproxy em Docker com Aceleração libvips
O Imgproxy foi desenvolvido em Go sobre a biblioteca libvips, a ferramenta de manipulação de imagem de código aberto mais rápida do mercado. É cerca de 5 vezes mais rápida do que o ImageMagick e consome até 85% menos memória RAM.
Aqui tens um ficheiro de configuração pronto para produção com o Docker Compose:
# docker-compose.yml
services:
imgproxy:
image: darthsim/imgproxy:v3.24
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
# Chaves Criptográficas Hexadecimais de 32 bytes
IMGPROXY_KEY: "9f8e7d6c5b4a3928170e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c"
IMGPROXY_SALT: "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
# Limites de segurança para evitar ataques DoS
IMGPROXY_CONCURRENCY: 8
IMGPROXY_MAX_SRC_RESOLUTION: 50
IMGPROXY_MAX_ANIMATION_FRAMES: 1
IMGPROXY_TTL: 31536000
# Ajustes de qualidade dos ficheiros
IMGPROXY_QUALITY: 80
IMGPROXY_AVIF_QUALITY: 65
IMGPROXY_WEBP_QUALITY: 75
# Acesso aos ficheiros locais
IMGPROXY_USE_S3: "false"
IMGPROXY_LOCAL_FILESYSTEM_ROOT: "/mnt/storage/media"
volumes:
- /mnt/storage/media:/mnt/storage/media:ro
deploy:
resources:
limits:
memory: 2048M
cpus: '4.0'
Repara como limitamos a concorrência e a resolução máxima da imagem original. Num serviço de alojamento gerido, estas barreiras protegem os teus servidores de picos inesperados de tráfego.
Assinatura Criptográfica HMAC-SHA256: Bloqueia Ataques de DoS
Se deixares o Imgproxy a correr em modo aberto (/insecure/...), qualquer utilizador malicioso pode descobrir o endereço e pedir tamanhos absurdos:
/insecure/resize:fill:9999:9999/.../insecure/resize:fill:401:300/.../insecure/resize:fill:402:300/...
Cada pedido destes força o processador a fazer cálculos pesados, deitando a tua máquina abaixo em poucos minutos. Para impedires isto, ativas a validação de assinaturas HMAC-SHA256.
PROCESSO DE ASSINATURA HMAC-SHA256
- Caminho a Assinar: /resize:fill:600:400/enlarge:0/plain/local:///banner.jpg@avif
- Junção de Bytes: [Salt em Binário] + [Caminho em Binário]
- Cálculo HMAC: Hash Criptográfico usando a tua Chave Secreta
- Codificação: Assinatura calculada: “qA3v8bZ9_1lM…”
- Endereço Seguro: https://media.x078.com/qA3v8bZ9_1lM/resize:fill:600:400/…
Aqui tens o exemplo de código em Node.js para gerares estas URLs no teu servidor:
// src/utils/imgproxySigner.ts
import crypto from 'node:crypto';
const CHAVE = process.env.IMGPROXY_KEY!;
const SALT = process.env.IMGPROXY_SALT!;
export function gerarUrlAssinada(
caminhoImagem: string,
largura: number,
altura: number,
formato: 'avif' | 'webp' | 'jpg' = 'avif'
): string {
const modo = 'fill';
const enlarge = 0;
// Converte o caminho original para base64 seguro
const urlCodificada = Buffer.from(`local:///${caminhoImagem}`)
.toString('base64url');
const caminho = `/resize:${modo}:${largura}:${altura}:${enlarge}/${urlCodificada}.${formato}`;
// Calcula o HMAC-SHA256 com a chave secreta
const hmac = crypto.createHmac('sha256', Buffer.from(CHAVE, 'hex'));
hmac.update(Buffer.from(SALT, 'hex'));
hmac.update(Buffer.from(caminho));
const assinatura = hmac.digest().toString('base64url');
return `https://media.x078.com/${assinatura}${caminho}`;
}
Se alguém tentar alterar as dimensões da URL na tentativa de sobrecarregar o servidor, a assinatura deixa de coincidir e o Imgproxy responde de imediato com 403 Forbidden sem gastar recursos da CPU.
Cache Inteligente com Nginx: Processa Uma Vez, Serve Infinitamente
O Imgproxy nunca deve processar a mesma imagem duas vezes. Ao colocares um proxy reverso com o Nginx à frente do contentor, a imagem gerada fica guardada em disco e é entregue de imediato nas visitas seguintes.
# /etc/nginx/conf.d/cache_media.conf
proxy_cache_path /var/cache/nginx/imgproxy
levels=1:2
keys_zone=MEDIA_CACHE:100m
max_size=15g
inactive=60d
use_temp_path=off;
server {
listen 443 ssl http2;
server_name media.x078.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_cache MEDIA_CACHE;
proxy_cache_key "$scheme$request_method$host$request_uri";
# Guarda imagens processadas em cache durante 30 dias
proxy_cache_valid 200 30d;
proxy_cache_valid 403 404 1m;
# Proteção contra pedidos simultâneos do mesmo ficheiro
proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
# Indica aos navegadores que o ficheiro nunca mais muda
add_header Cache-Control "public, max-age=31536000, immutable";
add_header X-Cache-Status $upstream_cache_status;
}
}
Com o parâmetro proxy_cache_lock on, se dez visitantes acederem ao teu site ao mesmo segundo e precisarem da mesma foto de produto, o Nginx deixa apenas o primeiro pedido passar ao Imgproxy. Os restantes nove aguardam uns milissegundos e recebem o ficheiro diretamente da cache. Podes encontrar o código-fonte e documentação deste projeto no GitHub.
Boas Práticas de Engenharia: Qualidade AVIF, Transparências e Marcas de Água
Para tirares o máximo rendimento desta tecnologia seguindo os métodos comprovados na WebXtek, aplica estas recomendações práticas:
- Afina a Qualidade do AVIF: Não uses valores de qualidade acima de 70 em ficheiros AVIF. Uma qualidade entre 60 e 65 garante nitidez percetiva perfeita e reduz o tamanho do ficheiro em 60% comparado com JPEG a 80.
- Respeita o Canal Alfa: Se converteres logótipos em PNG com fundo transparente para JPEG, o fundo fica preto. O Imgproxy resolve isso convertendo automaticamente para WebP ou AVIF, ou preenchendo o fundo com a cor pretendida através da opção
/background:ffffff/. - Aplica Marcas de Água Dinâmicas: Podes proteger fotos originais aplicando marcas de água de forma dinâmica (
/watermark:0.7:so:10:10:0.2/) sem teres de alterar o ficheiro original no disco.
Ao combinares o Imgproxy com assinaturas criptográficas e cache estática no Nginx, transformas por completo a velocidade de carregamento dos teus websites estáticos rápidos e garantes uma infraestrutura robusta e segura para os teus clientes.
Na prática, aplicas exatamente estes padrões operacionais em setores exigentes como saas empresarial b2b e especialistas em devops e arquitetura cloud. Quando alinhas a tua estrutura através de websites de alta performance e alojamento gerido para websites e aplicações, transformas boas práticas técnicas numa vantagem competitiva real e mensurável para o teu negócio.
[+] [ INDEX_DIRECTORY ] 13 tópicos ▼
- O Problema das Miniaturas Tradicionais: O Disco Fica Cheio Depressa
- Como Instalar o Imgproxy em Docker com Aceleração libvips
- Assinatura Criptográfica HMAC-SHA256: Bloqueia Ataques de DoS
- Cache Inteligente com Nginx: Processa Uma Vez, Serve Infinitamente
- Boas Práticas de Engenharia: Qualidade AVIF, Transparências e Marcas de Água
- Autor
- Perguntas Frequentes
- O que é o Imgproxy e porque é superior à geração prévia de miniaturas?
- Porque é que as URLs assinadas com HMAC-SHA256 são obrigatórias?
- Qual é a poupança real de largura de banda ao usar AVIF face a JPEG e WebP?
- O Imgproxy pode funcionar atrás de um proxy Nginx ou Cloudflare CDN?
- Nós Relacionados
- Sequência do Caminho
Perguntas Frequentes
O que é o Imgproxy e porque é superior à geração prévia de miniaturas?
O Imgproxy é um servidor de processamento de imagens ultrarrápido escrito em Go que transforma e converte ficheiros em tempo real com a biblioteca libvips. Em vez de guardares 10 variações estáticas no disco para cada foto enviada, o Imgproxy cria a dimensão e o formato exatos apenas quando o utilizador os pede.
Porque é que as URLs assinadas com HMAC-SHA256 são obrigatórias?
Sem assinaturas criptográficas, qualquer atacante pode criar scripts para pedir milhões de tamanhos arbitrários (por exemplo, 9999x9999 ou variações de pixel a pixel), esgotando a CPU e a memória do teu servidor num ataque DoS. A assinatura garante que o Imgproxy só atende pedidos gerados pelo teu próprio backend.
Qual é a poupança real de largura de banda ao usar AVIF face a JPEG e WebP?
O formato AVIF consegue uma compressão cerca de 50% mais eficiente do que o JPEG clássico e entre 20% a 30% superior ao WebP mantendo a mesma qualidade visual percetível, reduzindo de forma drástica o tempo de Largest Contentful Paint (LCP) em telemóveis.
O Imgproxy pode funcionar atrás de um proxy Nginx ou Cloudflare CDN?
Sim. Em ambientes de produção, o Imgproxy corre atrás do Nginx ou da Cloudflare. A primeira transformação demora cerca de 25 milissegundos e todas as visitas seguintes são servidas diretamente da cache de disco ou da edge com cabeçalhos imutáveis.
[ RELATED_NODES ]
> INICIAR_PROJETO
Precisa de um website que transmita confiança, apareça na pesquisa e dê mais força à sua presença digital? Comece a conversa aqui.