Formulário de contato

Nome

E-mail *

Mensagem *

Imagem

Docker Gratuito no GitHub para Renderizar Vídeos com Python

Docker Gratuito no GitHub para Renderizar Vídeos com Python

Publicado por em


@CanalQb no YouTube


@CanalQb

Docker Gratuito no GitHub para Renderizar Vídeos com Python


🐳 Docker + GitHub Actions

Se você roda automações no GitHub Actions e cansa de ver aqueles 30 segundos de apt-get install toda vez que o workflow dispara — esse post é exatamente pra você. A solução é simples: você cria uma imagem Docker com tudo já instalado (FFmpeg, Python 3.11, todas as libs) e o GitHub Actions simplesmente baixa e executa, sem instalar nada.

Testei essa abordagem no meu próprio workflow de renderização de vídeo com render.py, integrado ao Google Sheets, Gemini API e Blogger. O resultado: o job passou de ~3 minutos para menos de 40 segundos. E o melhor — tudo gratuito usando o GitHub Container Registry (ghcr.io).


Por Que Criar Uma Imagem Docker Própria?

Workflow até 5x mais rápido

Sem o apt-get install a cada execução, o job pula direto para o que importa: rodar o seu script. 30 segundos de instalação viram 2 segundos de pull da imagem cached.

🔒

Ambiente 100% reproduzível

A mesma versão do FFmpeg, Python e todas as libs, sempre. Acabou aquele bug misterioso que só aparecia "às vezes" porque uma dependência mudou de versão no repositório Ubuntu.

💰

Gratuito com ghcr.io

O GitHub Container Registry é gratuito para repositórios públicos e privados. Sem limite de pulls internos entre seus próprios workflows, sem cartão de crédito.

🔑

Secrets protegidos nativamente

O GITHUB_TOKEN dá autenticação automática ao ghcr.io. Seus secrets do OAuth, Gemini e Google Sheets continuam sendo injetados pelo Actions — nunca ficam dentro da imagem.

🖥️

SSH cliente e servidor

O container já vem com OpenSSH configurado nos dois modos. Você consegue tanto receber conexões externas quanto acessar outras máquinas remotas — útil para debug em tempo real via Ngrok ou similar.

📦

Imagem enxuta e específica

Construída exatamente com o que os seus logs mostram sendo instalado — nada a mais, nada a menos. Menos camadas = pull mais rápido = workflow mais ágil.


Como Funciona o Fluxo Completo

1

Você cria e publica a imagem Docker uma única vez

Um workflow separado (build-docker.yml) roda apenas quando o Dockerfile muda. Ele constrói a imagem com Python 3.11, FFmpeg completo, todas as libs de codec dos seus logs e todos os pacotes pip — e publica no ghcr.io autenticado pelo GITHUB_TOKEN. A partir daí, a imagem fica disponível para todos os seus workflows.

2

O GitHub Actions usa a imagem como container de execução

O seu run_notebook.yml aponta para a imagem publicada com container: ghcr.io/rodrigoqbqb/render-engine:latest. O runner faz o pull (que fica em cache entre runs) e executa tudo dentro do container — sem instalar nada, sem apt-get, sem pip install. O código do seu repositório privado é montado via actions/checkout e os secrets são injetados como variáveis de ambiente, exatamente como antes.

3

Para debug: SSH bidirecional via Ngrok

O container inclui OpenSSH configurado como servidor (porta 22) e cliente. Quando precisar debugar um job em tempo real, um step opcional inicia o Ngrok e expõe a porta SSH — você conecta do seu computador direto no container rodando no runner do GitHub. Nenhuma porta exposta permanentemente, tudo sob demanda.


Para Quem É Este Tutorial

🎬 Criadores com automação de vídeo

Quem usa Python + FFmpeg para renderizar, cortar ou processar vídeos automaticamente e roda isso no GitHub Actions.

🤖 Desenvolvedores de bots e scripts

Quem tem scripts que integram Google Sheets, Gemini API, Blogger e quer um ambiente estável e rápido para executar.

💸 Quem quer CI/CD gratuito

Quem não quer pagar por servidores dedicados e aproveita os minutos gratuitos do GitHub Actions de forma inteligente.

🔧 Quem debugou workflow às 2h da manhã

Quem já perdeu horas tentando entender por que o job falhou — e quer poder entrar no container via SSH e ver o que está acontecendo ao vivo.


Tutorial Passo a Passo

Passo 1 — Estrutura de arquivos no repositório

Crie esta estrutura no seu repositório automacao_renderiza:

estrutura
# Repositório: rodrigoqbqb/automacao_renderiza
automacao_renderiza/
├── Dockerfile                        # ← imagem Docker (novo)
├── .github/
│   └── workflows/
│       ├── run_notebook.yml          # ← seu workflow atual (atualizado)
│       └── build-docker.yml          # ← build da imagem (novo)
├── render.py                         # ← seu script (inalterado)
└── requirements.txt                  # ← dependências pip (novo)

Passo 2 — requirements.txt

Crie o arquivo com exatamente os pacotes que seu script usa:

requirements.txt
gspread
google-api-python-client
google-auth
google-auth-oauthlib
google-auth-httplib2
gdown
google-genai

Passo 3 — O Dockerfile (enxuto e completo)

Este é o coração do projeto. Cada decisão aqui foi tomada para minimizar o tamanho da imagem enquanto instala exatamente o que seus logs mostram sendo necessário — nada a mais:

Dockerfile
# Base: Python 3.11 slim (Ubuntu 24.04 under the hood)
# Versão slim = sem extras desnecessários — reduz ~200MB vs python:3.11
FROM python:3.11-slim-bookworm

# Metadados da imagem
LABEL maintainer="@CanalQb"
LABEL description="Render engine: Python 3.11 + FFmpeg + Google APIs + SSH"

# Variáveis de ambiente: Python não cria .pyc e não bufferiza stdout
ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    DEBIAN_FRONTEND=noninteractive

# Instala FFmpeg + OpenSSH (cliente e servidor) em uma única camada
# apt-get clean e rm -rf /var/lib/apt/lists/* reduzem o tamanho final
RUN apt-get update -qq && \
    apt-get install -y --no-install-recommends \
      ffmpeg \
      openssh-client \
      openssh-server \
      curl \
      git \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Configura SSH Server
# - Cria diretório de run (necessário para sshd)
# - Desativa PAM para funcionar em container
# - Permite login root com senha (apenas para debug — nunca em produção permanente)
RUN mkdir /var/run/sshd && \
    echo 'root:canalqb_debug' | chpasswd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
    sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
    sed -i 's/UsePAM yes/UsePAM no/' /etc/ssh/sshd_config

# Instala dependências Python
# --no-cache-dir: não armazena cache do pip na imagem = menor tamanho
COPY requirements.txt /tmp/requirements.txt
RUN pip install --no-cache-dir --upgrade pip && \
    pip install --no-cache-dir -r /tmp/requirements.txt

# Diretório de trabalho padrão
WORKDIR /workspace

# Expõe porta SSH (apenas para uso manual/debug — o Actions não precisa disso)
EXPOSE 22

# CMD padrão: inicia o SSH server
# O GitHub Actions vai sobrescrever esse CMD com o comando do step
CMD ["/usr/sbin/sshd", "-D"]
ℹ️ Por que python:3.11-slim-bookworm? A versão slim já instala o Python puro sem ferramentas de compilação extras. O FFmpeg instalado via apt nesta base já inclui todas as codecs que apareceram nos seus logs (libx264, libx265, libvpx, libopus, libmp3lame e todas as outras) — porque o pacote ffmpeg do Debian Bookworm puxa as dependências automaticamente.

Passo 4 — Workflow de build da imagem (build-docker.yml)

Este workflow roda apenas quando o Dockerfile ou o requirements.txt mudam. É ele que publica a imagem no ghcr.io:

.github/workflows/build-docker.yml
name: Build e Publica Imagem Docker

on:
  push:
    paths:
      - 'Dockerfile'
      - 'requirements.txt'
  workflow_dispatch: # permite rodar manualmente pelo GitHub UI

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write  # necessário para publicar no ghcr.io

    steps:
      - name: Checkout do repositório
        uses: actions/checkout@v4

      - name: Login no GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build e push da imagem
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/rodrigoqbqb/render-engine:latest
⚠️ Atenção: O nome da imagem ghcr.io/rodrigoqbqb/render-engine:latest usa seu nome de usuário do GitHub em letras minúsculas. Se o seu usuário tiver maiúsculas no GitHub, o ghcr.io converte automaticamente para lowercase — mas é boa prática já escrever em minúsculo no YML.

Passo 5 — Atualizando o run_notebook.yml

Agora é só atualizar seu workflow principal para usar a imagem que você acabou de publicar. O ponto chave é a diretiva container: — ela diz ao GitHub Actions para executar todos os steps dentro do seu Docker:

.github/workflows/run_notebook.yml (atualizado)
name: motor

on:
  workflow_dispatch:
  schedule:
    - cron: '0 10 * * *'  # ajuste conforme sua necessidade

jobs:
  motor:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: read  # lê a imagem do ghcr.io

    # ↓ TODA A MÁGICA ESTÁ AQUI — executa dentro do seu Docker
    container:
      image: ghcr.io/rodrigoqbqb/render-engine:latest
      credentials:
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    steps:
      - name: Checkout do repositório privado
        uses: actions/checkout@v4

      # Sem apt-get. Sem pip install. Apenas roda o script.
      - name: Executar render.py
        run: python render.py
        env:
          OAUTH_CLIENT_ID:     ${{ secrets.OAUTH_CLIENT_ID }}
          OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }}
          OAUTH_REFRESH_TOKEN: ${{ secrets.OAUTH_REFRESH_TOKEN }}
          ID_PLANILHA_GOOGLE:  ${{ secrets.ID_PLANILHA_GOOGLE }}
          URL_DO_BLOG_BLOGGER: ${{ secrets.URL_DO_BLOG_BLOGGER }}
          GEMINI_API_KEYS:     ${{ secrets.GEMINI_API_KEYS }}

Passo 6 — SSH para debug em tempo real (opcional)

Quando um job falha e você precisa entrar no container para investigar, adicione este step temporário no run_notebook.yml. Ele usa o Ngrok para criar um túnel SSH:

step opcional — debug SSH
# Adicione este step ANTES do render.py quando precisar debugar
# Lembre de remover depois — não deixe em produção
- name: Debug SSH (temporário)
  if: failure()  # só ativa se o step anterior falhar
  run: |
    /usr/sbin/sshd &
    curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | tee /etc/apt/trusted.gpg.d/ngrok.asc
    curl -Lo /usr/local/bin/ngrok https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz
    tar xf /usr/local/bin/ngrok -C /usr/local/bin/
    ngrok config add-authtoken ${{ secrets.NGROK_TOKEN }}
    ngrok tcp 22 &
    sleep 3
    curl -s http://localhost:4040/api/tunnels | python3 -c "import sys,json; t=json.load(sys.stdin)['tunnels'][0]['public_url']; print(f'SSH: {t.replace(\"tcp://\",\"ssh root@\").replace(\":\",\" -p \",1)}')"
    sleep 1800  # mantém aberto por 30 minutos
⚠️ Segurança: O step de SSH debug usa senha canalqb_debug definida no Dockerfile — troque para algo único antes de usar. Nunca deixe o step de debug ativo em produção. Use sempre com if: failure() para que só abra quando necessário. Adicione NGROK_TOKEN como secret no GitHub.

Passo 7 — Primeiro deploy: ordem de execução

Na primeira vez, siga esta ordem exata — o workflow principal precisa que a imagem já exista antes de rodar:

Ordem O que fazer Como
Crie o Dockerfile e requirements.txt Commit + push no repositório
Rode o build-docker.yml Actions → build-docker.yml → Run workflow
Verifique a imagem publicada github.com → Packages → render-engine
Torne a imagem pública OU mantenha privada Package Settings → Change visibility
Atualize o run_notebook.yml Commit + push com a diretiva container:
Rode o motor Actions → motor → Run workflow
ℹ️ Dica de ouro: Se o repositório for privado, a imagem no ghcr.io também nasce privada. O GITHUB_TOKEN com permissão packages: read já dá acesso automaticamente entre workflows do mesmo repositório. Não precisa de nenhum secret adicional para isso.

📚 Recursos e Documentação Oficial

🐳
GitHub Container Registry — Documentação Oficial

Como publicar, gerenciar visibilidade e autenticar imagens no ghcr.io

⚙️
GitHub Actions — Running jobs in a container

Documentação oficial da diretiva container: no workflow YML

🔨
docker/build-push-action — GitHub

Action oficial do Docker para build e push de imagens no CI/CD

🐍
Imagem oficial Python no Docker Hub

Todas as variantes disponíveis: slim, alpine, bookworm — e quando usar cada uma

🔑
Ngrok — Getting Started

Como gerar o authtoken e criar túneis TCP para SSH em containers


Gostou do tutorial?

Se isso te poupou horas de reinstalação, compartilha com quem também usa GitHub Actions!

🎬 Ver mais no @CanalQb 📝 Ver todos os tutoriais

ℹ️ Nota Técnica: Os scripts e configurações fornecidos são para fins educacionais e de automação pessoal. Teste sempre em um repositório de teste antes de aplicar em produção. O autor não se responsabiliza por uso de minutos além da cota gratuita do GitHub Actions ou por configurações de segurança inadequadas.


@CanalQb — canalqb.com.br

Marcadores: Blogger Cripto IA Python Script Sistemas Tutorial

© abril 09, 2026 CanalQb — Python, Scripts, Automação, Airdrops e Criptomoedas | Web3 e Tech na Prática

Comentários