Skip to content

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)

SituacaoExemploSolucao no K3s
docker.sock mountPortainer, Watchtower, DozzlehostPath mount do containerd socket, ou nao usar (temos ArgoCD/Rancher)
network_mode: hostPi-hole, NetdatahostNetwork: true no pod
privileged: trueVPN containers, hardware accesssecurityContext.privileged: true
Docker Compose com depends_on, buildDev environments com build localBuild fora (CI), deploy a imagem pronta
Multi-container com shared filesystemApps legadas com sidecar via volumesPod 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 fazO que ja temos
Deploy de apps via GitArgoCD (GitOps)
TLS automatico (Let’s Encrypt)Traefik (ja configurado)
Dashboard de appsRancher + ArgoCD UI
Multi-serverK3s multi-node
RollbackArgoCD (revert commit)
MonitoramentoOpenObserve + 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 Python

Operacoes 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 benchSem OperatorCom Operator
bench new-siteSSH + executar manualmenteCriar FrappeSite YAML (ou git push)
bench install-app lmsSSH + executarCampo apps: [lms] no FrappeSite
bench migrateSSH apos cada updateOperator faz automaticamente
bench backupCron manual ou scriptSiteBackup CRD com schedule
Escalar workersEditar supervisor.confAutoscaling nativo (KEDA/HPA)

CRDs do Operator:

CRDO que fazEquivalente bench
FrappeBenchInfraestrutura compartilhada (gunicorn, workers, nginx, redis)bench init + bench setup
FrappeSiteUm site Frappe (DB, apps instaladas, dominio)bench new-site + bench install-app
SiteBackupBackup agendado ou manualbench backup via cron
SiteJobExecutar comando benchbench migrate, bench console, etc.

Operator vs Helm chart oficial

AspectoHelm chart (frappe/helm)Frappe Operator
Abstrai o bench?Parcialmente — voce configura Jobs de create-site, valores de workers manualmenteSim — FrappeBench + FrappeSite = declarativo
Multi-site1 Helm release = 1 site1 FrappeBench = N FrappeSites (multi-tenant)
Operacoes (migrate, backup)Criar Jobs K8s manualmenteSiteJob/SiteBackup CRD
AutoscalingHPA manualKEDA integrado por componente
GitOpsFunciona (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)

Terminal window
helm repo add frappe-operator https://vyogotech.github.io/frappe-operator/helm-repo
helm install frappe-operator frappe-operator/frappe-operator \
--namespace frappe-operator-system --create-namespace

Isso 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/existente
apiVersion: vyogo.tech/v1alpha1
kind: FrappeBench
metadata:
name: cpps-bench
namespace: frappe
spec:
frappeVersion: "version-15"
imageConfig:
repository: ghcr.io/frappe/lms
storageSize: 8Gi
storageClassName: local-path

Passo 3 — Criar o site LMS

apps/frappe/lms-site.yaml
apiVersion: vyogo.tech/v1alpha1
kind: FrappeSite
metadata:
name: lms
namespace: frappe
spec:
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 Traefik

Passo 4 — Application ArgoCD

apps/argocd/frappe.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: frappe
namespace: argocd
spec:
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=true

Passo 5 — Rota no Traefik

config/traefik/routes/lms.yaml
apiVersion: v1
kind: Service
metadata:
name: lms-backend
namespace: traefik
spec:
ports:
- port: 8080
targetPort: <NODEPORT>
---
apiVersion: v1
kind: Endpoints
metadata:
name: lms-backend
namespace: traefik
subsets:
- addresses:
- ip: 192.168.0.51
ports:
- port: <NODEPORT>
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: lms
namespace: traefik
spec:
entryPoints: [websecure]
routes:
- match: Host(`lms.cppsunesp.org`)
kind: Rule
services:
- name: lms-backend
port: 8080
tls:
certResolver: letsencrypt

Passo 6 — Commit e push

Terminal window
git add apps/frappe/ apps/argocd/frappe.yaml config/traefik/routes/lms.yaml
git commit -m "feat: adicionar Frappe LMS via Operator"
git push
# ArgoCD sincroniza automaticamente

Adicionar 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/v1alpha1
kind: FrappeSite
metadata:
name: erp
namespace: frappe
spec:
benchRef:
name: cpps-bench # mesmo bench!
siteName: erp.cppsunesp.org
apps:
- erpnext
- hrms

Sem 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