ADRIANOLAUREANO← Artigos
SÉRIE CASULO · 02/03OVERLAYFSRUST

Como uma imagem de container vira um sistema de arquivos executável?

Se o container é um processo isolado, de onde surgem /bin, /etc, bibliotecas e todos os arquivos que ele acredita serem seu computador?

ARTIGO 25 · CASULO 0.2 · IMAGENS E FILESYSTEM

3camadas de imagem

1camada gravável

1volume persistente

CASULO · UM PROCESSO, VÁRIAS FRONTEIRAS
HOST LINUXPID 4821CPU · RAM · REDE/var/lib/casulo
CASULO 0.2
PIDMNTUTSNET
processomesmo kernel · outra visão
KERNEL COMPARTILHADOnamespaces · cgroups · mounts · signals

VOCABULÁRIO VISUAL

As peças do kernel que entram em cena.

01Imagemcamadas imutáveis e configuração
02Rootfsfilesystem montado para o processo
03Mountligação de uma árvore a um diretório
04OverlayFSjunção de camadas numa visão
05Copy-on-Writecópia criada somente ao escrever
06Volumedados com ciclo de vida independente
O nome técnico vem depois do problema. Consulte este mapa quando uma peça reaparecer.
01
O processo não recebe um disco; recebe uma árvore.
rootfs é a raiz da visão

No Linux, arquivos de vários dispositivos e pseudo-filesystems aparecem numa única árvore. O rootfs é a árvore que o processo passa a enxergar como /. Isso conecta a série ao RaizFS: diretórios organizam nomes, enquanto mounts ligam árvores diferentes.

ObjetoO que éCiclo de vida
Imagemcamadas imutáveis + manifestoreutilizável
Containerconfiguração + processo + camada gravávelaté remoção
Volumedados externos montadosindependente do container
02
chroot muda um caminho, não cria uma fronteira completa.
Mount namespace e pivot_root

chroot altera a resolução de caminhos para um processo, mas não separa mounts, PIDs, rede nem recursos; processos privilegiados podem escapar em cenários conhecidos. No Casulo, preparamos a árvore num mount namespace e usamos pivot_root para tornar a raiz nova ativa e abandonar a antiga.

ANTES                         DEPOIS DO pivot_root
host /                         imagem /
└─ /var/lib/casulo/merged      ├─ /bin
                              ├─ /etc
                              ├─ /proc  ← montado no namespace
                              └─ /.old  ← desmontado e removido
A raiz antiga não permanece acessível ao processo.

Montamos /proc depois de entrar no PID namespace, garantindo que a árvore de processos combine com a visão interna.

03
Uma imagem é conteúdo verificável, não um container parado.
Manifesto, configuração e hashes

Como no artigo do compactador, precisamos de manifesto, conteúdo e integridade. O formato didático .cas guarda uma configuração e uma lista ordenada de hashes.

{
  "format": "casulo.image.v1",
  "entrypoint": ["/bin/servidor"],
  "env": ["MODO=producao"],
  "layers": ["sha256:91af...", "sha256:3b02..."]
}

Cada camada é endereçada pelo hash de seu conteúdo. Dois manifestos com a mesma base referenciam os mesmos bytes. O Casulo calcula o hash ao importar e antes de montar; corrupção não vira uma camada silenciosa.

04
Construir é transformar instruções em camadas.
Um arquivo declarativo pequeno
# Casulo.toml
base = "./bases/minima.tar"
copy = [["./servidor", "/bin/servidor"]]
entrypoint = ["/bin/servidor", "--porta", "8080"]
env = ["MODO=producao"]

Não copiamos Dockerfile: nosso formato possui apenas as operações explicadas. O construtor valida destinos relativos à raiz, rejeita .., normaliza permissões, empacota cada mudança e grava atomicamente em store/blobs/sha256/.

$ casulo build -f Casulo.toml -t servidor:1
camada 91af… reutilizada
camada 3b02… criada (184 KiB)
imagem servidor:1 → manifestos/7d9c….json

$ casulo images
NOME         ID        CAMADAS   TAMANHO ÚNICO
servidor:1   7d9c…     2         184 KiB
05
Escrever sem alterar a imagem.
OverlayFS e Copy-on-Write
merged/  ← visão entregue ao processo
   ▲
   ├─ upper/  alterações deste container
   ├─ work/   área técnica do OverlayFS
   └─ lower/  camada app : camada base (somente leitura)

leitura: procura de upper para lower
escrita: copia o arquivo para upper e modifica a cópia
Copy-on-Write significa copiar quando houver escrita, não copiar a imagem inteira ao iniciar.

Ao remover o container, upper pode desaparecer; as camadas da imagem permanecem. Whiteouts representam remoções na visão superior sem apagar a camada inferior.

06
Persistência precisa pertencer a algo mais duradouro.
Volumes e bind mounts

Um volume gerenciado vive em diretório validado do Casulo e é montado dentro do rootfs. Um bind mount expõe caminho explícito do host. O segundo é mais perigoso: o Casulo exige caminho absoluto permitido e modo ro ou rw.

container A ── /dados ─┐
                       ├── volume clientes
container removido ────┘      │ permanece
container B ── /dados ─────────┘
Remover processo e camada gravável não remove automaticamente o volume.
07
Da imagem ao processo em nove passos.
Casulo 0.2
resolver nome → verificar manifesto → verificar hashes
 → criar upper/work/merged → montar OverlayFS
 → montar volumes e /proc → pivot_root
 → executar entrypoint → desmontar em ordem inversa
Cada mount entra numa pilha de rollback antes da etapa seguinte.
$ sudo casulo run servidor:1 --volume clientes:/dados
[casulo] image=7d9c… layers=2 writable=01J…
servidor ouvindo em :8080
Critérios objetivos

O mesmo hash é reutilizado por duas imagens; alterar arquivo cria cópia somente em upper; a camada original mantém hash; volume sobrevive à remoção; falha após o terceiro mount desmonta exatamente três recursos.

08
Filesystem isolado ainda não controla fome nem conversa.
O que falta para 1.0

O Casulo 0.2 monta um rootfs isolado e gravável, mas o processo ainda pode consumir toda CPU e memória e sua rede não possui topologia própria. O próximo capítulo adicionará cgroups, redução de privilégios, network namespace e ciclo de vida observável.

Fontes: pivot_root(2), documentação oficial do OverlayFS e OCI Image Specification.

PROJETO COMPLETO · ESTADO EXATO DESTE CAPÍTULO

Baixe o Casulo 0.2.

Pacote exclusivo deste artigo, com código Rust, exemplos, testes condicionais para Linux e roteiro de limpeza. Não execute em produção nem use imagens desconhecidas.

Baixar Casulo 0.2 (.zip)Linux · Rust · requer privilégios documentados

O que este artigo fez você pensar?

Dúvidas, experiências e contrapontos ajudam a próxima pessoa a enxergar o assunto por outro ângulo.

Todos passam por moderação. Ao enviar, você concorda com a política de privacidade.

Receba os próximos artigos.

Uma mensagem quando uma nova investigação estiver pronta. Só isso.