Skip to content

feat: suporte a Docker com configuração por variável de ambiente - #17

Merged
jailsonsb2 merged 6 commits into
mainfrom
feat/docker
Aug 2, 2026
Merged

feat: suporte a Docker com configuração por variável de ambiente#17
jailsonsb2 merged 6 commits into
mainfrom
feat/docker

Conversation

@jailsonsb2

Copy link
Copy Markdown
Owner

Closes #16

Adiciona suporte a Docker ao player. Como o projeto é 100% estático, o Dockerfile em si é a parte fácil — o trabalho de verdade foi tornar o player configurável sem editar arquivo-fonte, senão trocar a URL do stream exigiria rebuildar a imagem.

Como funciona

A configuração saiu do js/script.js para um config.js carregado antes dele. No Docker, esse arquivo é gerado na subida do container a partir das variáveis de ambiente, por um script em /docker-entrypoint.d/ — diretório que a imagem oficial do nginx já executa antes de subir o servidor, sem precisar sobrescrever o ENTRYPOINT.

docker run -d -p 8080:80 \
  -e RADIO_NAME="Minha Rádio" \
  -e URL_STREAMING="https://stream.zeno.fm/..." \
  ghcr.io/jailsonsb2/radioplayer:latest

Trocar a rádio é mudar a variável e reiniciar. Sem rebuild.

Variável Padrão
RADIO_NAME Jailson Web Rádio
URL_STREAMING stream da demo
API_URL / FALLBACK_API_URL derivadas do stream
ACCENT_COLOR / BG_COLOR tema do CSS
THEME_COLOR #0b0e13
PWA_NAME / PWA_SHORT_NAME seguem o RADIO_NAME

Compatibilidade — nada quebra

O js/script.js mantém os valores atuais como fallback. Sem config.js, o player roda idêntico a hoje. GitHub Pages, Vercel, Netlify e "copiar a pasta pro servidor" seguem funcionando sem nenhuma mudança.

Bug do service worker que já existia

Ao mexer no cache apareceu um problema anterior a este PR: o service-worker.js listava caminhos absolutos (/index.html, /js/script.js). A demo fica em /RadioPlayer/, então esses caminhos davam 404, o cache.addAll rejeitava e a instalação do service worker falhava inteira — ou seja, o PWA nunca funcionou no GitHub Pages.

Verificado servindo o site em subdiretório:

/index.html    -> 404
/js/script.js  -> 404

Corrigido junto:

  • caminhos relativos ao worker (funciona na raiz e em subdiretório)
  • cache.add individual — um arquivo ausente não derruba mais a instalação
  • config.js e manifest.json em rede-primeiro, senão trocar a variável de ambiente não surtiria efeito para quem já visitou a página
  • requisições cross-origin passam direto: interceptar o stream de áudio, a API de metadados e as capas não traz benefício e pode atrapalhar o player

Testes

Imagem buildada e executada localmente, com stream real:

  • Player renderizado no browser a partir do container, tocando metadados reais (nome da rádio da env var, música atual, capa, histórico com clipes)
  • Botão "Instalar app" aparecendo — o manifest.json gerado é válido e o PWA é instalável
  • Stream real respondendo HTTP 200 audio/mpeg, icy-name: Jailson Webradio
  • Dois containers da mesma imagem com env vars diferentes → configurações diferentes, sem rebuild
  • Acentuação correta no nome da rádio, ponta a ponta
  • Healthcheck healthy, fallback de rota, LICENSE servida

Três bugs foram encontrados justamente por rodar a imagem, e um deles o CI não pegaria, porque docker build não executa healthcheck:

  1. Container ficava unhealthy com o site no ar. O HEALTHCHECK usava localhost, que dentro do container resolve primeiro para ::1; o nginx escuta só em IPv4 (listen [::]:80 quebra em container sem IPv6) → connection refused. Passou a usar 127.0.0.1.
  2. Cache-Control duplicadoexpires somado a add_header mandava o header duas vezes.
  3. charset não declarado — o nome da rádio com acento dependia do browser adivinhar a codificação.

Publicação

Workflow multi-arch (linux/amd64 + linux/arm64, cobrindo Raspberry Pi e NAS ARM) que builda em pull request e publica no GHCR na main e em tags. O nome da imagem é passado para minúsculas porque o GHCR não aceita maiúscula e o repositório se chama RadioPlayer.

A LICENSE vai embarcada na imagem: quem redistribui ou hospeda tem obrigação de AGPL.


@ameer1234567890 obrigado pela sugestão — se puder testar a branch antes do merge, ajuda bastante.

🤖 Generated with Claude Code

jailsonsb2 and others added 6 commits August 2, 2026 15:29
Extrai RADIO_NAME e URL_STREAMING do js/script.js para um config.js
carregado antes dele. O script.js mantem os valores atuais como fallback,
entao o player continua funcionando identico se o config.js nao existir.

Prepara o terreno para o Docker, onde o config.js e gerado na subida do
container a partir de variaveis de ambiente (issue #16).

Co-Authored-By: Claude Opus 5 <[email protected]>
Dockerfile baseado em nginx:alpine servindo os estaticos. Um script em
/docker-entrypoint.d/ gera config.js e manifest.json a partir das variaveis
de ambiente na subida do container, entao trocar de radio nao exige
rebuildar a imagem.

- docker/nginx.conf: no-store nos arquivos gerados e no-cache no
  service-worker/index.html, senao mudar a env var nao surte efeito
- .gitattributes: eol=lf nos arquivos do container (CRLF quebra o shebang)
- LICENSE embarcada na imagem (obrigacao da AGPL para quem hospeda)

Closes #16

Co-Authored-By: Claude Opus 5 <[email protected]>
Os caminhos absolutos ('/index.html', '/js/script.js') davam 404 quando o
site fica em subdiretorio, como o /RadioPlayer/ do GitHub Pages: o
cache.addAll rejeitava e a instalacao do service worker falhava inteira,
entao o PWA nunca funcionou na demo. Agora sao relativos ao proprio worker,
o que serve tanto a raiz (Docker) quanto o subdiretorio.

Outras correcoes na mesma linha:
- cache.add individual: um arquivo ausente nao derruba mais a instalacao
- config.js e manifest.json em rede-primeiro, senao trocar a variavel de
  ambiente no Docker nao surtiria efeito para quem ja visitou a pagina
- requisicoes cross-origin passam direto: interceptar o stream de audio, a
  API de metadados e as capas nao traz beneficio e pode atrapalhar o player
- clients.claim() para o worker novo assumir na hora

Co-Authored-By: Claude Opus 5 <[email protected]>
Workflow multi-arch (amd64 + arm64, cobrindo Raspberry Pi e NAS ARM) que
builda em pull request e publica na main e em tags. O nome da imagem e
passado para minusculas porque o GHCR nao aceita maiuscula e o repositorio
se chama RadioPlayer.

README: secao Docker com a tabela de variaveis de ambiente, e a secao de
configuracao agora aponta para o config.js em vez do js/script.js.

Co-Authored-By: Claude Opus 5 <[email protected]>
Achados ao rodar a imagem de verdade:

- HEALTHCHECK usava localhost, que dentro do container resolve primeiro para
  ::1. O nginx escuta so em IPv4 (listen [::]:80 quebra em container sem
  IPv6), entao o healthcheck dava "connection refused" com o site no ar e o
  container ficava unhealthy. Agora usa 127.0.0.1.
- nginx nao declarava charset: o nome da radio com acento dependia do browser
  adivinhar a codificacao. Agora charset utf-8 tambem em js e json.
- expires somado a add_header Cache-Control mandava o header duplicado
  ("max-age=3600,public, max-age=3600"). Ficou so o expires.

Co-Authored-By: Claude Opus 5 <[email protected]>
Acrescenta o que so ficou claro rodando a imagem: tamanho real (~76 MB),
healthcheck embarcado, e o aviso de por tras de proxy reverso com HTTPS
(sem origem segura o browser bloqueia o convite de instalar o PWA e a
Media Session API).

Deixa explicito tambem que o container serve o player, nao os metadados:
capa, letra e now playing continuam vindo das APIs publicas.

Co-Authored-By: Claude Opus 5 <[email protected]>
@netlify

netlify Bot commented Aug 2, 2026

Copy link
Copy Markdown

Deploy Preview for allstream ready!

Name Link
🔨 Latest commit 80ecadf
🔍 Latest deploy log https://app.netlify.com/projects/allstream/deploys/6a6fa9ee0c0162000878be5c
😎 Deploy Preview https://deploy-preview-17--allstream.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@jailsonsb2
jailsonsb2 merged commit d23db7c into main Aug 2, 2026
4 of 5 checks passed
@jailsonsb2 jailsonsb2 mentioned this pull request Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docker Setup

1 participant