Deploy de Repositorio Privado
Este tutorial mostra como deployar uma aplicacao a partir de um repositorio GitHub privado. Requer um Personal Access Token (PAT) para autenticacao.
Cenario
Voce tem um repo privado (devborlot/meu-app-sys) com um backend Flask que
precisa ser deployado em producao. O repo usa Dockerfile para build.
Pre-requisitos
- Runner instalado (
runner initexecutado) - Docker e Traefik rodando no servidor
- Dominio apontando pro servidor
- GitHub Personal Access Token (Fine-grained ou Classic)
Passo 1: Criar GitHub Token
Fine-grained PAT (recomendado)
- Acesse GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens
- Clique em "Generate new token"
- Configure:
- Token name:
runner-deploy - Expiration: 90 days (ou custom)
- Repository access: Only select repositories → selecione
meu-app-sys - Permissions:
- Contents: Read-only
- Metadata: Read-only
- Token name:
- Copie o token gerado (comeca com
github_pat_...)
Classic PAT (alternativa)
- GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate new token com scope
repo - Copie o token (comeca com
ghp_...)
O Runner armazena o token encriptado (AES-GCM) no state file e usa
GIT_ASKPASSpara autenticar — o token nunca aparece emps aux,.git/configou logs.
Passo 2: Preparar o Repositorio
.deploy.yml
project: meu-app
system: sys
port: 8000
# Modo BUILD com Dockerfile
build:
context: .
dockerfile: Dockerfile
# NOTA: bloco `github:` foi DEPRECATED em v2.16.0 — o repo é resolvido
# automaticamente do state file (registrado via `runner add --repo --branch`).
version:
source: file # opcional desde v2.18.2
file: version.json
field: version
# Desde v2.18.2, generator default emite `source: git-commit`
# (deploys auto-versionados via SHA).
networks:
- public
- mysql
- redis
environment:
FLASK_ENV: production
PYTHONPATH: /app/src
healthcheck:
path: /health
start_period: 45s # Grace period para Flask cold start
interval: 10s
timeout: 5s
retries: 5
instances:
production:
domain: sys.meusite.com.br
source:
type: dist
keep_versions: 3Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY src/ ./src/
ENV PYTHONPATH=/app/src
ENV FLASK_ENV=production
EXPOSE 8000
HEALTHCHECK --interval=10s --timeout=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health')" || exit 1
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "main:app"]Dica: declarar
HEALTHCHECKno Dockerfile evita problemas com imagens que nao temcurl/wget. O Runner respeita o healthcheck da imagem.
Build e Push para dist
git checkout dist 2>/dev/null || git checkout -b dist
# Copiar artefatos (backend Python = src/ direto)
cp -r src/ ./src/
cp requirements.txt Dockerfile .deploy.yml version.json ./
git add .
git commit -m "deploy: v1.0.0"
git push origin distPasso 3: Registrar no Runner (com Token)
No servidor de producao:
runner add --repo devborlot/meu-app-sys --branch main --token ghp_xxxYYYzzz123O Runner:
- Usa o token para clonar o repo privado (via GIT_ASKPASS)
- Valida o
.deploy.yml(parse + validacao semantica — verifica que Dockerfile existe, port > 0, healthcheck path absoluto) - Encripta e salva o token no state file
- Registra a app
Com ckey (para proteger secrets)
Se o app precisa de variaveis sensiveis (.env com senhas de DB, API keys):
runner add --repo devborlot/meu-app-sys --branch main \
--token ghp_xxxYYYzzz123 \
--ckey "minha-chave-de-encriptacao-forte"A ckey permite recuperacao zero-touch dos secrets em caso de perda do servidor.
Verificar
runner list
# Deve mostrar: meu-app (sys) — up_to_date
# Verificar config
runner validate /data/apps/meu-app/.deploy.ymlPasso 4: Configurar Environment
Antes do deploy, configure as variaveis de ambiente:
# Variaveis normais (vao para .env)
runner env set meu-app --key DB_HOST --value mysql
runner env set meu-app --key DB_NAME --value meu_app_db
# Secrets (vao para .secrets, encriptados se ckey configurada)
runner env set meu-app --key DB_PASSWORD --value "senha_segura" --secret
runner env set meu-app --key JWT_SECRET --value "chave_jwt_longa" --secret
# Verificar
runner env status meu-appPasso 5: Deploy
runner deploy meu-app -VOutput esperado:
[1/7] FETCH Baixando codigo fonte...
[2/7] PREPARE Preparando versao v1.0.0...
[3/7] SECURITY Verificando seguranca...
[4/7] BUILD Building image meu-app:v1.0.0...
[5/7] CONTAINER Iniciando container...
[DEPLOY] Honoring HEALTHCHECK declared by image 'meu-app:v1.0.0'
[6/7] HEALTH Verificando saude...
Health check wait: 135s (start=45s, interval=10s, timeout=5s, retries=5)
Container meu-app_production_v1-0-0 is healthy
[7/7] ROUTING Configurando Traefik...Passo 6: Verificar
# Health check
curl -s https://sys.meusite.com.br/health | python3 -m json.tool
# Container
docker ps | grep meu-app
# Logs
docker logs meu-app_production_v1-0-0 --tail 20Passo 7: Automatizar
Cron (detecta pushes)
*/5 * * * * /opt/runner/runner fetch --deploy --json >> /var/log/runner-fetch.json 2>&1Ou service mode (recomendado v2.2.0+)
runner service init --port 9090
runner service start
# Scheduler faz fetch automaticamente + gerencia canary + signalsRotacionar Token
Quando o token expirar:
# Gerar novo token no GitHub
# Atualizar no Runner:
runner edit meu-app --token ghp_novoToken456
# Verificar que o fetch funciona:
runner fetch meu-appA partir da v2.1.0, se o token expirar, o Runner mostra:
Falha de autenticacao no git: o token salvo esta ausente ou expirou. Rode: runner edit <app> --token <ghp_...>
Exemplo Completo: Fluxo de Release
# 1. Desenvolvimento (branch dev)
git checkout dev
# ... commits ...
git push origin dev
# 2. Release (merge para main + tag)
git checkout main
git merge dev --no-ff -m "release: v1.1.0"
git tag -a v1.1.0 -m "Release v1.1.0"
git push origin main --tags
# 3. Build + push para dist
git checkout dist
rm -rf src/ && cp -r ../src ./src/
cp requirements.txt Dockerfile .deploy.yml version.json ./
git add . && git commit -m "deploy: v1.1.0"
git push origin dist
# 4. Runner detecta e deploya (via cron ou service mode)
# Ou force: ssh servidor "runner fetch --deploy"
# 5. Voltar para dev
git checkout dev && git merge main && git push origin devTroubleshooting
"could not read Username"
Token ausente ou expirado:
runner edit meu-app --token ghp_novoToken
runner fetch meu-app --force"Config invalido em .deploy.yml at line N"
Erro de YAML com localizacao exata. Corrija o campo indicado na branch dist.
Build falha (Dockerfile)
# Testar build localmente:
docker build -t test .
docker run --rm test
# Verificar que Dockerfile esta na dist:
ls /data/apps/meu-app/pull/DockerfileHealth check falha
Ver o guia de healthcheck para diagnostico detalhado.