Pular para o conteúdo principal
Versão: 0.14.0

Runtime Container

:::danger Apenas Containers Linux

O runtime container suporta apenas imagens de container Linux baseadas em Debian (ex: debian:stable-slim).

NÃO suportado:

  • Imagens baseadas em Alpine — Ambientes baseados em musl possuem diferenças comportamentais sutis que reduzem a confiabilidade do runtime
  • Imagens de container Windows — Não há shell POSIX disponível

Requisitos de plataforma:

  • Linux: Funciona nativamente com Docker ou Podman
  • macOS: Funciona com Docker Desktop (usa VMs Linux internamente)
  • Windows: Requer Docker Desktop com backend WSL2 em modo de containers Linux

Scripts são executados usando /bin/sh dentro do container, o que requer um ambiente com shell POSIX compatível.

:::

:::info Escopo da Detecção de Alpine

O Invowk rejeita imagens com nome exato alpine ou terminando com /alpine (após remover tags e digests). Imagens com "alpine" em outra parte do nome (ex: go-alpine-builder ou myorg/alpine-tools) não são automaticamente rejeitadas. Evite todas as imagens baseadas em musl independentemente do nome — a política é sobre confiabilidade do runtime, não apenas correspondência de nome de imagem.

:::

O runtime container executa comandos dentro de um container Docker ou Podman. Ele fornece isolamento completo e reprodutibilidade - seu comando executa no exato mesmo ambiente toda vez.

Como Funciona

Quando você executa um comando com o runtime container, o Invowk™:

  1. Baixa ou constrói a imagem do container (se necessário)
  2. Monta o diretório do invowkfile dentro do container
  3. Executa o script dentro do container
  4. Transmite a saída de volta para seu terminal

Uso Básico

{
name: "build"
implementations: [
{
script: {content: "echo 'Hello from container' && ls /workspace"}
runtimes: [{
name: "container"
image: "debian:stable-slim"
}]
platforms: [{name: "linux"}]
}
]
}
invowk cmd myproject build

Fontes de Imagem de Container

Você deve especificar exatamente uma origem: uma image ou um containerfile; eles são mutuamente exclusivos.

Imagens Pré-construídas

runtimes: [{
name: "container"
image: "debian:stable-slim"
}]

Imagem genérica recomendada:

  • debian:stable-slim - Base Debian mínima para exemplos portáveis de container

Containerfile Personalizado

Construa a partir de um Containerfile/Dockerfile local:

runtimes: [{
name: "container"
containerfile: "./Containerfile" // Relative to invowkfile
}]

Caminhos de Containerfile são relativos ao diretório do invowkfile. Segmentos de diretório pai (..) são rejeitados antes da resolução do caminho, enquanto nomes comuns com pontos, como Containerfile..backup, continuam válidos.

Exemplo de Containerfile:

FROM debian:stable-slim

RUN apt-get update && apt-get install -y \
ca-certificates \
git \
make

WORKDIR /workspace

Montagem de Volumes

Monte diretórios adicionais no container:

runtimes: [{
name: "container"
image: "debian:stable-slim"
volumes: [
"./data:/data", // Relative path
"/tmp:/tmp:ro", // Absolute path, read-only
"${HOME}/.cache:/cache" // Environment variable
]
}]

O diretório do invowkfile é automaticamente montado em /workspace.

Mapeamento de Portas

Exponha portas do container para o host:

runtimes: [{
name: "container"
image: "debian:stable-slim"
ports: [
"3000:3000", // Host:Container
"8080:80" // Map container port 80 to host port 8080
]
}]

Containers Persistentes

Por padrão, o Invowk inicia um container efêmero para cada comando e o remove quando o processo termina. Defina persistent em um bloco de runtime container quando um comando deve reutilizar um container duradouro entre invocações:

runtimes: [{
name: "container"
image: "debian:stable-slim"
persistent: {
create_if_missing: true
// Optional. When omitted, invowk derives a stable invowk-* name
// from the fully-qualified command namespace.
name: "myproject-build"
}
}]

Quando create_if_missing é true, o Invowk cria o container se ele não existir, marca-o como gerenciado pelo Invowk, inicia-o e executa o comando com docker exec ou podman exec nas próximas execuções. Se name for omitido, o Invowk deriva um nome estável que começa com invowk- a partir do namespace totalmente qualificado do comando.

Você também pode direcionar um container em execução já existente pela CLI:

# Target an already-running container by portable name
invowk cmd build --ivk-container-name dev-shell

Nomes explícitos devem ser nomes portáveis de Docker/Podman: letras minúsculas, dígitos, ., _ ou -, começando com uma letra minúscula ou dígito.

Usando Interpretadores

Como o runtime native, containers suportam interpretadores personalizados:

Auto-Detecção pelo Shebang

{
name: "analyze"
implementations: [{
platforms: [{name: "linux"}]
script: {content: """
#!/usr/bin/env python3
import sys
print(f"Python {sys.version} in container!")
"""}
runtimes: [{
name: "container"
image: "python:3-slim"
}]
}]
}

Interpretador Explícito

{
name: "analyze"
implementations: [{
script: {
content: """
import sys
print(f"Running on Python {sys.version_info.major}")
"""
interpreter: "python3"
}
runtimes: [{
name: "container"
image: "python:3-slim"
}]
platforms: [{name: "linux"}]
}]
}

Variáveis de Ambiente

Variáveis de ambiente são passadas para o container:

{
name: "deploy"
env: {
vars: {
DEPLOY_ENV: "production"
API_URL: "https://api.example.com"
}
}
implementations: [{
platforms: [{name: "linux"}]
script: {content: """
echo "Deploying to $DEPLOY_ENV"
echo "API: $API_URL"
"""}
runtimes: [{
name: "container"
image: "debian:stable-slim"
}]
}]
}

Acesso SSH ao Host

Às vezes seu container precisa executar comandos no sistema host. Habilite acesso SSH de volta ao host:

{
name: "deploy from container"
implementations: [{
script: {content: """
# Connection credentials are provided via environment variables
echo "SSH Host: $INVOWK_SSH_HOST"
echo "SSH Port: $INVOWK_SSH_PORT"

# Connect back to host
sshpass -p $INVOWK_SSH_TOKEN ssh -o StrictHostKeyChecking=no
$INVOWK_SSH_USER@$INVOWK_SSH_HOST -p $INVOWK_SSH_PORT
'echo "Hello from host!"'
"""}
runtimes: [{
name: "container"
image: "debian:stable-slim"
enable_host_ssh: true // Enable SSH server
}]
platforms: [{name: "linux"}]
}]
}

Variáveis de Ambiente SSH

Quando enable_host_ssh: true, estas variáveis estão disponíveis:

VariávelDescrição
INVOWK_SSH_ENABLEDDefinido como true quando o SSH está ativo
INVOWK_SSH_HOSTEndereço do host (ex: host.docker.internal)
INVOWK_SSH_PORTPorta do servidor SSH
INVOWK_SSH_USERNome de usuário (invowk)
INVOWK_SSH_TOKENToken de autenticação com escopo da execução

Segurança

  • Cada execução de comando recebe um token único
  • Tokens são revogados quando o comando termina
  • O servidor SSH apenas aceita autenticação baseada em token
  • O servidor é encerrado após a execução do comando

Requisitos do Container

Seu container precisa de sshpass ou similar para SSH baseado em senha:

FROM debian:stable-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
openssh-client sshpass \
&& rm -rf /var/lib/apt/lists/*

Dependências

Dependências de container são validadas dentro do container:

{
name: "build"
depends_on: {
tools: [
// Always checked on the host, regardless of runtime
{alternatives: ["go"]},
{alternatives: ["make"]}
]
filepaths: [
// Paths checked on the host filesystem
{alternatives: ["go.mod"]}
]
}
implementations: [{
platforms: [{name: "linux"}]
script: {content: "test -f /workspace/invowkfile.cue && echo ready"}
runtimes: [{
name: "container"
image: "debian:stable-slim"
}]
}]
}

Engine de Container

O Invowk suporta tanto Docker quanto Podman. Configure sua preferência:

// ~/.config/invowk/config.cue
container_engine: "podman" // or "docker"

Se não configurado, o Invowk tenta:

  1. podman (se disponível)
  2. docker (fallback)

Diretório de Trabalho

Por padrão, o diretório do invowkfile é montado em /workspace e usado como diretório de trabalho:

{
name: "build"
implementations: [{
platforms: [{name: "linux"}]
script: {content: """
pwd # Outputs: /workspace
ls # Shows your project files
"""}
runtimes: [{
name: "container"
image: "debian:stable-slim"
}]
}]
}

Sobrescreva com workdir:

{
name: "build package"
workdir: "./frontend" // Mounted and used as workdir
implementations: [{
platforms: [{name: "linux"}]
script: {content: "./build.sh"}
runtimes: [{
name: "container"
image: "debian:stable-slim"
}]
}]
}

Exemplo Completo

Aqui está um comando container com todos os recursos:

{
name: "check workspace"
description: "Check project files in an isolated container"
env: {
vars: {
APP_ENV: "test"
CHECK_MODE: "full"
}
}
depends_on: {
tools: [{alternatives: ["sh"]}]
filepaths: [{alternatives: ["invowkfile.cue"]}]
}
implementations: [{
script: {content: """
echo "Environment: $APP_ENV"
test -f /workspace/invowkfile.cue
echo "Workspace ready"
"""}
runtimes: [{
name: "container"
image: "debian:stable-slim"
volumes: [
"${HOME}/.cache/invowk:/cache:ro" // Reuse host-side cache data
]
}]
platforms: [{name: "linux"}]
}]
}

Auto-provisionamento

Quando container.auto_provision.enabled é true (padrão), o Invowk cria uma imagem derivada em cache ao anexar uma pequena camada de provisionamento sobre a sua imagem base (seja a image especificada ou a imagem construída pelo Containerfile/Dockerfile). Essa camada inclui o binário do invowk e quaisquer módulos, para que comandos invowk estejam disponíveis dentro do container.

O auto-provisionamento ocorre em toda execução de container, não apenas no modo interativo. A imagem derivada é cacheada como invowk-provisioned:<hash> e reutilizada; se o provisionamento falhar, o Invowk avisa e usa a imagem base.

Modo Interativo

O runtime container suporta totalmente o modo interativo (-i). Execuções interativas usam a mesma camada provisionada descrita acima (quando habilitada) e adicionam a infraestrutura de TUI no host, habilitando:

  • Componentes TUI como overlays modais
  • Suporte completo a PTY para prompts de senha e confirmações
  • Integração transparente com o terminal do host
# Executar um comando de container interativamente
invowk cmd myproject build -i -r container

Quando você executa com -i, o Invowk:

  1. Usa a camada de imagem provisionada (se habilitada)
  2. Inicia um servidor TUI no host
  3. Encaminha requisições TUI do container para o host
  4. Renderiza overlays no seu terminal

Isso significa que seus scripts podem usar comandos invowk tui dentro de containers:

{
name: "deploy container"
implementations: [{
platforms: [{name: "linux"}]
script: {content: """
# This TUI confirm appears as an overlay on your terminal
if invowk tui confirm "Deploy to production?"; then
echo "Deploying..."
./deploy.sh
fi
"""}
runtimes: [{
name: "container"
image: "debian:stable-slim"
}]
}]
}
dica

A imagem provisionada é cacheada como invowk-provisioned:<hash>, então execuções subsequentes são rápidas.

Vantagens

  • Reprodutibilidade: Mesmo ambiente em todos os lugares
  • Isolamento: Sem poluição do sistema host
  • Controle de versão: Fixe versões exatas de ferramentas
  • Paridade CI/CD: Builds locais correspondem aos builds do CI
  • Builds limpos: Ambiente novo cada vez

Limitações

  • Performance: Overhead de inicialização do container
  • Espaço em disco: Imagens consomem armazenamento
  • Complexidade: Necessário gerenciar imagens
  • Acesso ao host: Limitado sem ponte SSH

Quando Usar Container

  • Builds reproduzíveis: Quando consistência importa
  • Pipelines CI/CD: Corresponder ambientes local e CI
  • Projetos legados: Isolar versões antigas de ferramentas
  • Onboarding de equipe: Sem necessidade de instalação local de ferramentas
  • Builds em ambiente limpo: Testar sem poluição do host

Solução de Problemas

Container Não Inicia

# Verificar se engine de container está disponível
docker --version # ou: podman --version

# Verificar se imagem existe
docker images | grep golang

Primeira Execução Lenta

A primeira execução baixa a imagem. Execuções subsequentes são mais rápidas:

# Pré-baixar a imagem genérica recomendada
docker pull debian:stable-slim

Problemas de Permissão

No Linux, você pode precisar configurar permissões do container:

# Para Docker
sudo usermod -aG docker $USER

# Para Podman (rootless)
# Geralmente funciona sem configuração

Próximos Passos