Runtime Container
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. Apenas imagens com nome exato
alpineou terminando com/alpine(após remover tags/digests) são rejeitadas. Imagens comogo-alpine-builderoumyorg/alpine-toolsNÃO são rejeitadas. - Imagens de container Windows (
mcr.microsoft.com/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.
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™:
- Baixa ou constrói a imagem do container (se necessário)
- Monta o diretório do invowkfile dentro do container
- Executa o script dentro do container
- Transmite a saída de volta para seu terminal
Uso Básico
{
name: "build"
implementations: [
{
script: "go build -o /workspace/bin/app ./..."
runtimes: [{
name: "container"
image: "golang:1.26"
}]
platforms: [{name: "linux"}]
}
]
}
invowk cmd myproject build
Fontes de Imagem de Container
Você deve especificar ou uma image ou um containerfile - eles são mutuamente exclusivos.
Imagens Pré-construídas
runtimes: [{
name: "container"
image: "golang:1.26"
}]
Imagens comuns:
debian:stable-slim- Debian mínimo (imagem base recomendada)golang:1.26- Desenvolvimento Gonode:20- Desenvolvimento Node.jspython:3-slim- Desenvolvimento Python
Containerfile Personalizado
Construa a partir de um Containerfile/Dockerfile local:
runtimes: [{
name: "container"
containerfile: "./Containerfile" // Relative to invowkfile
}]
Exemplo de Containerfile:
FROM golang:1.26
RUN apt-get update && apt-get install -y
make
git
WORKDIR /workspace
Montagem de Volumes
Monte diretórios adicionais no container:
runtimes: [{
name: "container"
image: "golang:1.26"
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: "node:20"
ports: [
"3000:3000", // Host:Container
"8080:80" // Map container port 80 to host port 8080
]
}]
Usando Interpretadores
Como o runtime native, containers suportam interpretadores personalizados:
Auto-Detecção pelo Shebang
{
name: "analyze"
implementations: [{
platforms: [{name: "linux"}]
script: """
#!/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: """
import sys
print(f"Running on Python {sys.version_info.major}")
"""
runtimes: [{
name: "container"
image: "python:3-slim"
interpreter: "python3"
}]
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: """
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: """
# 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ável | Descrição |
|---|---|
INVOWK_SSH_ENABLED | Definido como true quando o SSH está ativo |
INVOWK_SSH_HOST | Endereço do host (ex: host.docker.internal) |
INVOWK_SSH_PORT | Porta do servidor SSH |
INVOWK_SSH_USER | Nome de usuário (invowk) |
INVOWK_SSH_TOKEN | Token de autenticação único |
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: [
// Checked inside the container, not on host
{alternatives: ["go"]},
{alternatives: ["make"]}
]
filepaths: [
// Paths relative to container's /workspace
{alternatives: ["go.mod"]}
]
}
implementations: [{
platforms: [{name: "linux"}]
script: "make build"
runtimes: [{
name: "container"
image: "golang:1.26"
}]
}]
}
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:
podman(se disponível)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: """
pwd # Outputs: /workspace
ls # Shows your project files
"""
runtimes: [{
name: "container"
image: "debian:stable-slim"
}]
}]
}
Sobrescreva com workdir:
{
name: "build frontend"
workdir: "./frontend" // Mounted and used as workdir
implementations: [{
platforms: [{name: "linux"}]
script: "npm run build"
runtimes: [{
name: "container"
image: "node:20"
}]
}]
}
Exemplo Completo
Aqui está um comando container com todos os recursos:
{
name: "build and test"
description: "Build and test in isolated container"
env: {
vars: {
GO_ENV: "test"
CGO_ENABLED: "0"
}
}
depends_on: {
tools: [{alternatives: ["go"]}]
filepaths: [{alternatives: ["go.mod"]}]
}
implementations: [{
script: """
echo "Go version: $(go version)"
echo "Building..."
go build -o /workspace/bin/app ./...
echo "Testing..."
go test -v ./...
echo "Done!"
"""
runtimes: [{
name: "container"
image: "golang:1.26"
volumes: [
"${HOME}/go/pkg/mod:/go/pkg/mod:ro" // Cache Go dependencies
]
}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
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:
- Usa a camada de imagem provisionada (se habilitada)
- Inicia um servidor TUI no host
- Encaminha requisições TUI do container para o host
- 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: """
# 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"
}]
}]
}
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 imagens
docker pull golang:1.26
docker pull node:20
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
- Runtime Native - Para velocidade de desenvolvimento
- Runtime Virtual - Para scripts multiplataforma
- Dependências - Declarar requisitos do comando