Docker vs Kubernetes
Docker vs K8s — Quando cada um faz sentido
Principio geral
Qualquer container Docker roda no K8s. O K3s usa containerd por baixo, que puxa as mesmas imagens Docker Hub/GHCR. A questao nao e compatibilidade tecnica — e se o overhead de K8s se justifica.
Situacoes que parecem incompativeis com K8s (mas nao sao)
| Situacao | Exemplo | Solucao no K3s |
|---|---|---|
docker.sock mount | Portainer, Watchtower, Dozzle | hostPath mount do containerd socket, ou nao usar (temos ArgoCD/Rancher) |
network_mode: host | Pi-hole, Netdata | hostNetwork: true no pod |
privileged: true | VPN containers, hardware access | securityContext.privileged: true |
Docker Compose com depends_on, build | Dev environments com build local | Build fora (CI), deploy a imagem pronta |
| Multi-container com shared filesystem | Apps legadas com sidecar via volumes | Pod multi-container (mesmo conceito, syntax diferente) |
docker build dentro do container (DinD) | CI runners (Jenkins, GitLab Runner) | Kaniko, Buildah (rootless), ou DinD com socket mount |
O unico caso onde K8s genuinamente nao funciona e quando o app depende da Docker API (ex: Portainer gerenciando containers Docker, Coolify orquestrando deploys via Docker daemon).
Caso concreto: Coolify (nao roda no K8s)
O que e: PaaS self-hosted (alternativa a Heroku/Vercel). Gerencia deploys de containers em servidores via SSH + Docker.
Dependencia critica: Docker Engine 24+ obrigatorio. Coolify usa a Docker API diretamente para orquestrar containers, fazer builds, gerenciar volumes e redes. Nao e so “roda em Docker” — ele depende da Docker API como ferramenta de orquestracao.
Roda no K8s? Nao. Coolify e um orquestrador Docker — colocar dentro do K8s seria colocar um orquestrador dentro de outro orquestrador. Nao faz sentido tecnico nem operacional.
Faz sentido usar Coolify na nossa infra? Nao — tudo que ele faz ja temos:
| O que Coolify faz | O que ja temos |
|---|---|
| Deploy de apps via Git | ArgoCD (GitOps) |
| TLS automatico (Let’s Encrypt) | Traefik (ja configurado) |
| Dashboard de apps | Rancher + ArgoCD UI |
| Multi-server | K3s multi-node |
| Rollback | ArgoCD (revert commit) |
| Monitoramento | OpenObserve + OTel |
Coolify resolve o problema de quem nao tem orquestracao. Nos ja temos — seria duplicacao.
Quando Coolify faria sentido: se fosse a unica ferramenta de infra (substituindo K3s + ArgoCD + Traefik). Mas como ja temos tudo isso, Coolify seria redundante.
Caso concreto: Frappe LMS (roda no K8s)
O que e: plataforma de cursos online baseada no Frappe Framework (Python + Vue).
Deploy oficial: Docker Compose (docker compose up -d). Tambem tem hosting gerenciado (Frappe Cloud).
Dependencias: Frappe bench (CLI), MariaDB/PostgreSQL, Redis, Nginx (proxy interno).
Roda no K8s? Sim — e a abordagem recomendada para producao.
O problema real: frappe-bench
O frappe-bench e a ferramenta CLI do Frappe para gerenciar sites, apps, workers e migracao. Foi desenhado para uma VM com acesso SSH:
frappe-bench/├── sites/lms.cppsunesp.org/ ← config do site├── apps/frappe/ + apps/lms/ ← codigo das apps├── config/supervisor.conf ← gerencia processos└── env/ ← virtualenv PythonOperacoes tipicas: bench new-site, bench install-app lms, bench migrate, bench backup. Tudo imperativo, via terminal. Isso nao encaixa em K8s (declarativo, GitOps).
Solucao: Frappe Operator
O Frappe Operator (v3.1.0, Apache 2.0) transforma operacoes imperativas do bench em recursos declarativos K8s. Voce nunca mais roda bench manualmente — o Operator faz internamente.
| Operacao bench | Sem Operator | Com Operator |
|---|---|---|
bench new-site | SSH + executar manualmente | Criar FrappeSite YAML (ou git push) |
bench install-app lms | SSH + executar | Campo apps: [lms] no FrappeSite |
bench migrate | SSH apos cada update | Operator faz automaticamente |
bench backup | Cron manual ou script | SiteBackup CRD com schedule |
| Escalar workers | Editar supervisor.conf | Autoscaling nativo (KEDA/HPA) |
CRDs do Operator:
| CRD | O que faz | Equivalente bench |
|---|---|---|
| FrappeBench | Infraestrutura compartilhada (gunicorn, workers, nginx, redis) | bench init + bench setup |
| FrappeSite | Um site Frappe (DB, apps instaladas, dominio) | bench new-site + bench install-app |
| SiteBackup | Backup agendado ou manual | bench backup via cron |
| SiteJob | Executar comando bench | bench migrate, bench console, etc. |
Operator vs Helm chart oficial
| Aspecto | Helm chart (frappe/helm) | Frappe Operator |
|---|---|---|
| Abstrai o bench? | Parcialmente — voce configura Jobs de create-site, valores de workers manualmente | Sim — FrappeBench + FrappeSite = declarativo |
| Multi-site | 1 Helm release = 1 site | 1 FrappeBench = N FrappeSites (multi-tenant) |
| Operacoes (migrate, backup) | Criar Jobs K8s manualmente | SiteJob/SiteBackup CRD |
| Autoscaling | HPA manual | KEDA integrado por componente |
| GitOps | Funciona (Helm values) | Mais natural (CRDs = recursos K8s) |
Recomendacao: usar o Operator. E mais K8s-native e esconde a complexidade do bench.
Como implementar o Frappe LMS no K3s
Passo 1 — Instalar o Operator (uma vez)
helm repo add frappe-operator https://vyogotech.github.io/frappe-operator/helm-repohelm install frappe-operator frappe-operator/frappe-operator \ --namespace frappe-operator-system --create-namespaceIsso pode ser gerenciado pelo ArgoCD como qualquer outra app (criar apps/argocd/frappe-operator.yaml).
Passo 2 — MariaDB compartilhado
apps/frappe/mariadb.yaml# Pode usar o MariaDB que o Operator fornece como exemplo,# ou apontar para um MariaDB externo/existenteapiVersion: vyogo.tech/v1alpha1kind: FrappeBenchmetadata: name: cpps-bench namespace: frappespec: frappeVersion: "version-15" imageConfig: repository: ghcr.io/frappe/lms storageSize: 8Gi storageClassName: local-pathPasso 3 — Criar o site LMS
apps/frappe/lms-site.yamlapiVersion: vyogo.tech/v1alpha1kind: FrappeSitemetadata: name: lms namespace: frappespec: benchRef: name: cpps-bench siteName: lms.cppsunesp.org apps: - lms dbConfig: provider: mariadb mode: shared mariadbRef: name: frappe-mariadb namespace: frappe ingress: enabled: false # usamos IngressRoute no TraefikPasso 4 — Application ArgoCD
apps/argocd/frappe.yamlapiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: frappe namespace: argocdspec: project: default source: repoURL: https://github.com/colabhd/devops.git targetRevision: main path: apps/frappe destination: server: https://kubernetes.default.svc namespace: frappe syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=truePasso 5 — Rota no Traefik
config/traefik/routes/lms.yamlapiVersion: v1kind: Servicemetadata: name: lms-backend namespace: traefikspec: ports: - port: 8080 targetPort: <NODEPORT>---apiVersion: v1kind: Endpointsmetadata: name: lms-backend namespace: traefiksubsets: - addresses: - ip: 192.168.0.51 ports: - port: <NODEPORT>---apiVersion: traefik.io/v1alpha1kind: IngressRoutemetadata: name: lms namespace: traefikspec: entryPoints: [websecure] routes: - match: Host(`lms.cppsunesp.org`) kind: Rule services: - name: lms-backend port: 8080 tls: certResolver: letsencryptPasso 6 — Commit e push
git add apps/frappe/ apps/argocd/frappe.yaml config/traefik/routes/lms.yamlgit commit -m "feat: adicionar Frappe LMS via Operator"git push# ArgoCD sincroniza automaticamenteAdicionar mais apps Frappe no futuro
O grande beneficio do Operator: o FrappeBench e compartilhado. Para adicionar ERPNext, HR ou Wiki, basta criar outro FrappeSite apontando para o mesmo bench:
apiVersion: vyogo.tech/v1alpha1kind: FrappeSitemetadata: name: erp namespace: frappespec: benchRef: name: cpps-bench # mesmo bench! siteName: erp.cppsunesp.org apps: - erpnext - hrmsSem reinstalar nada. O Operator cria o site, instala as apps, configura o DB.
Arvore de decisao
O app precisa rodar em producao (usuarios acessam)?├── Sim → K3s + ArgoCD + Traefik│ (TLS, monitoramento, rollback, GitOps — tudo pronto)│└── Nao (teste, prototipo, ferramenta interna temporaria) │ ├── Precisa da Docker API? (ex: Coolify, Portainer, CI runner com DinD) │ └── Sim → Docker Compose em VM dedicada (nao no K3s) │ └── Nao precisa da Docker API? └── K3s (mesmo para testes — e rapido com os templates)Resumo
- 99% dos apps rodam no K3s sem problema — incluindo apps com docker-compose.yaml oficial
- Apps que dependem da Docker API (Coolify, Portainer, CI com DinD) sao a excecao real
- Para esses casos, Docker Compose numa VM separada e a solucao mais simples
- Nao precisamos de um segundo orquestrador (Uncloud, Coolify) — o K3s + ArgoCD ja cobre