mirror of
https://github.com/dunglas/frankenphp.git
synced 2025-12-24 13:38:11 +08:00
feat: add Brazilian Portuguese translation (#1645)
* feat: add Brazilian Portuguese * Translate file README.md * Update file README.md * Translate file docs/classic.md * Translate file docs/worker.md * Translate file docs/early-hints.md * Translate file docs/mercure.md * Translate file docs/x-sendfile.md * Translate file docs/config.md * Translate file docs/docker.md * Minor fixes * Translate file docs/production.md * Translate file CONTRIBUTING.md * Minor fixes * Translate file docs/performance.md * Minor fixes * Translate file docs/embed.md * Minor fixes * Minor fixes * Translate file docs/static.md * Translate file docs/compile.md * Minor fixes * Translate file docs/metrics.md * Translate file docs/laravel.md * Translate file docs/known-issues.md * Minor fixes * Translate file docs/github-actions.md * Fix build * Fix build * fix: remove text already translated * feat: update translation * fix: format comments based on other translations
This commit is contained in:
238
docs/pt-br/CONTRIBUTING.md
Normal file
238
docs/pt-br/CONTRIBUTING.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# Contribuindo
|
||||
|
||||
## Compilando o PHP
|
||||
|
||||
### Com Docker (Linux)
|
||||
|
||||
Crie a imagem Docker de desenvolvimento:
|
||||
|
||||
```console
|
||||
docker build -t frankenphp-dev -f dev.Dockerfile .
|
||||
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -p 443:443/udp -v $PWD:/go/src/app -it frankenphp-dev
|
||||
```
|
||||
|
||||
A imagem contém as ferramentas de desenvolvimento usuais (Go, GDB, Valgrind,
|
||||
Neovim...) e usa os seguintes locais de configuração do PHP:
|
||||
|
||||
- php.ini: `/etc/frankenphp/php.ini`.
|
||||
Um arquivo `php.ini` com configurações de desenvolvimento é fornecido por
|
||||
padrão.
|
||||
- Arquivos de configuração adicionais: `/etc/frankenphp/php.d/*.ini`.
|
||||
- Extensões PHP: `/usr/lib/frankenphp/modules/`.
|
||||
|
||||
Se a sua versão do Docker for anterior à 23.0, a compilação falhará devido ao
|
||||
[problema de padrão do `.dockerignore`](https://github.com/moby/moby/pull/42676).
|
||||
Adicione diretórios ao `.dockerignore`.
|
||||
|
||||
```patch
|
||||
!testdata/*.php
|
||||
!testdata/*.txt
|
||||
+!caddy
|
||||
+!internal
|
||||
```
|
||||
|
||||
### Sem Docker (Linux e macOS)
|
||||
|
||||
[Siga as instruções para compilar a partir dos fontes](compile.md) e passe a
|
||||
flag de configuração `--debug`.
|
||||
|
||||
## Executando a suite de testes
|
||||
|
||||
```console
|
||||
go test -tags watcher -race -v ./...
|
||||
```
|
||||
|
||||
## Módulo Caddy
|
||||
|
||||
Construa o Caddy com o módulo Caddy FrankenPHP:
|
||||
|
||||
```console
|
||||
cd caddy/frankenphp/
|
||||
go build -tags watcher,brotli,nobadger,nomysql,nopgx
|
||||
cd ../../
|
||||
```
|
||||
|
||||
Execute o Caddy com o módulo Caddy FrankenPHP:
|
||||
|
||||
```console
|
||||
cd testdata/
|
||||
../caddy/frankenphp/frankenphp run
|
||||
```
|
||||
|
||||
O servidor está escutando em `127.0.0.1:80`:
|
||||
|
||||
> [!NOTE]
|
||||
> Se você estiver usando o Docker, terá que vincular a porta 80 do contêiner ou
|
||||
> executar de dentro do contêiner.
|
||||
|
||||
```console
|
||||
curl -vk http://127.0.0.1/phpinfo.php
|
||||
```
|
||||
|
||||
## Servidor de teste mínimo
|
||||
|
||||
Construa o servidor de teste mínimo:
|
||||
|
||||
```console
|
||||
cd internal/testserver/
|
||||
go build
|
||||
cd ../../
|
||||
```
|
||||
|
||||
Execute o servidor de teste:
|
||||
|
||||
```console
|
||||
cd testdata/
|
||||
../internal/testserver/testserver
|
||||
```
|
||||
|
||||
O servidor está escutando em `127.0.0.1:8080`:
|
||||
|
||||
```console
|
||||
curl -v http://127.0.0.1:8080/phpinfo.php
|
||||
```
|
||||
|
||||
## Construindo imagens Docker localmente
|
||||
|
||||
Imprima o plano do bake:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --print
|
||||
```
|
||||
|
||||
Construa imagens FrankenPHP para amd64 localmente:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/amd64"
|
||||
```
|
||||
|
||||
Construa imagens FrankenPHP para arm64 localmente:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/arm64"
|
||||
```
|
||||
|
||||
Construa imagens FrankenPHP do zero para arm64 e amd64 e envie para o Docker
|
||||
Hub:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --no-cache --push
|
||||
```
|
||||
|
||||
## Depurando falhas de segmentação com compilações estáticas
|
||||
|
||||
1. Baixe a versão de depuração do binário do FrankenPHP do GitHub ou crie sua
|
||||
própria compilação estática personalizada, incluindo símbolos de depuração:
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder.args.DEBUG_SYMBOLS=1 \
|
||||
--set "static-builder.platform=linux/amd64" \
|
||||
static-builder
|
||||
docker cp $(docker create --name static-builder-musl dunglas/frankenphp:static-builder-musl):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp
|
||||
```
|
||||
|
||||
2. Substitua sua versão atual do `frankenphp` pelo executável de depuração do
|
||||
FrankenPHP.
|
||||
3. Inicie o FrankenPHP normalmente (alternativamente, você pode iniciar o
|
||||
FrankenPHP diretamente com o GDB: `gdb --args frankenphp run`).
|
||||
4. Anexe ao processo com o GDB:
|
||||
|
||||
```console
|
||||
gdb -p `pidof frankenphp`
|
||||
```
|
||||
|
||||
5. Se necessário, digite `continue` no shell do GDB.
|
||||
6. Faça o FrankenPHP travar.
|
||||
7. Digite `bt` no shell do GDB.
|
||||
8. Copie a saída.
|
||||
|
||||
## Depurando falhas de segmentação no GitHub Actions
|
||||
|
||||
1. Abra o arquivo `.github/workflows/tests.yml`.
|
||||
2. Habilite os símbolos de depuração do PHP:
|
||||
|
||||
```patch
|
||||
- uses: shivammathur/setup-php@v2
|
||||
# ...
|
||||
env:
|
||||
phpts: ts
|
||||
+ debug: true
|
||||
```
|
||||
|
||||
3. Habilite o `tmate` para se conectar ao contêiner:
|
||||
|
||||
```patch
|
||||
- name: Set CGO flags
|
||||
run: echo "CGO_CFLAGS=$(php-config --includes)" >> "$GITHUB_ENV"
|
||||
+ - run: |
|
||||
+ sudo apt install gdb
|
||||
+ mkdir -p /home/runner/.config/gdb/
|
||||
+ printf "set auto-load safe-path /\nhandle SIG34 nostop noprint pass" > /home/runner/.config/gdb/gdbinit
|
||||
+ - uses: mxschmitt/action-tmate@v3
|
||||
```
|
||||
|
||||
4. Conecte-se ao contêiner.
|
||||
5. Abra o `frankenphp.go`.
|
||||
6. Habilite o `cgosymbolizer`:
|
||||
|
||||
```patch
|
||||
- //_ "github.com/ianlancetaylor/cgosymbolizer"
|
||||
+ _ "github.com/ianlancetaylor/cgosymbolizer"
|
||||
```
|
||||
|
||||
7. Baixe o módulo: `go get`.
|
||||
8. No contêiner, você pode usar o GDB e similares:
|
||||
|
||||
```console
|
||||
go test -tags watcher -c -ldflags=-w
|
||||
gdb --args frankenphp.test -test.run ^MyTest$
|
||||
```
|
||||
|
||||
9. Quando a falha for corrigida, reverta todas essas alterações.
|
||||
|
||||
## Recursos diversos de desenvolvimento
|
||||
|
||||
- [PHP embedding in uWSGI](https://github.com/unbit/uwsgi/blob/master/plugins/php/php_plugin.c)
|
||||
- [PHP embedding in NGINX Unit](https://github.com/nginx/unit/blob/master/src/nxt_php_sapi.c)
|
||||
- [PHP embedding in Go (go-php)](https://github.com/deuill/go-php)
|
||||
- [PHP embedding in Go (GoEmPHP)](https://github.com/mikespook/goemphp)
|
||||
- [PHP embedding in C++](https://gist.github.com/paresy/3cbd4c6a469511ac7479aa0e7c42fea7)
|
||||
- [Extending and Embedding PHP por Sara Golemon](https://books.google.fr/books?id=zMbGvK17_tYC&pg=PA254&lpg=PA254#v=onepage&q&f=false)
|
||||
- [What the heck is TSRMLS_CC, anyway?](http://blog.golemon.com/2006/06/what-heck-is-tsrmlscc-anyway.html)
|
||||
- [SDL bindings](https://pkg.go.dev/github.com/veandco/go-sdl2@v0.4.21/sdl#Main)
|
||||
|
||||
## Recursos relacionados ao Docker
|
||||
|
||||
- [Definição do arquivo Bake](https://docs.docker.com/build/customize/bake/file-definition/)
|
||||
- [`docker buildx build`](https://docs.docker.com/engine/reference/commandline/buildx_build/)
|
||||
|
||||
## Comando útil
|
||||
|
||||
```console
|
||||
apk add strace util-linux gdb
|
||||
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1
|
||||
```
|
||||
|
||||
## Traduzindo a documentação
|
||||
|
||||
Para traduzir a documentação e o site para um novo idioma, siga estes passos:
|
||||
|
||||
1. Crie um novo diretório com o código ISO de 2 caracteres do idioma no
|
||||
diretório `docs/` deste repositório.
|
||||
2. Copie todos os arquivos `.md` da raiz do diretório `docs/` para o novo
|
||||
diretório (sempre use a versão em inglês como fonte para tradução, pois está
|
||||
sempre atualizada).
|
||||
3. Copie os arquivos `README.md` e `CONTRIBUTING.md` do diretório raiz para o
|
||||
novo diretório.
|
||||
4. Traduza o conteúdo dos arquivos, mas não altere os nomes dos arquivos, nem
|
||||
traduza strings que comecem com `> [!` (é uma marcação especial para o
|
||||
GitHub).
|
||||
5. Crie um pull request com as traduções.
|
||||
6. No
|
||||
[repositório do site](https://github.com/dunglas/frankenphp-website/tree/main),
|
||||
copie e traduza os arquivos de tradução nos diretórios `content/`, `data/` e
|
||||
`i18n/`.
|
||||
7. Traduza os valores no arquivo YAML criado.
|
||||
8. Abra um pull request no repositório do site.
|
||||
125
docs/pt-br/README.md
Normal file
125
docs/pt-br/README.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# FrankenPHP: Servidor de aplicações moderno para PHP
|
||||
|
||||
<h1 align="center"><a href="https://frankenphp.dev/pt-br"><img src="frankenphp.png" alt="FrankenPHP" width="600"></a></h1>
|
||||
|
||||
O FrankenPHP é um servidor de aplicações moderno para PHP, construído sobre o
|
||||
servidor web [Caddy](https://caddyserver.com/).
|
||||
|
||||
O FrankenPHP oferece superpoderes às suas aplicações PHP graças aos seus
|
||||
recursos impressionantes: [_Early Hints_](early-hints.md),
|
||||
[modo worker](worker.md), [recursos em tempo real](mercure.md), suporte
|
||||
automático a HTTPS, HTTP/2 e HTTP/3...
|
||||
|
||||
O FrankenPHP funciona com qualquer aplicação PHP e torna seus projetos Laravel e
|
||||
Symfony mais rápidos do que nunca, graças às suas integrações oficiais com o
|
||||
modo worker.
|
||||
|
||||
O FrankenPHP também pode ser usado como uma biblioteca Go independente para
|
||||
incorporar PHP em qualquer aplicação usando `net/http`.
|
||||
|
||||
[**Saiba mais** em _frankenphp.dev_](https://frankenphp.dev/pt-br) e neste
|
||||
conjunto de slides:
|
||||
|
||||
<a href="https://dunglas.dev/2022/10/frankenphp-the-modern-php-app-server-written-in-go/"><img src="https://dunglas.dev/wp-content/uploads/2022/10/frankenphp.png" alt="Slides" width="600"></a>
|
||||
|
||||
## Começando
|
||||
|
||||
### Binário independente
|
||||
|
||||
Fornecemos binários estáticos do FrankenPHP para Linux e macOS contendo o
|
||||
[PHP 8.4](https://www.php.net/releases/8.4/pt_BR.php) e as extensões PHP mais
|
||||
populares.
|
||||
|
||||
No Windows, use [WSL](https://learn.microsoft.com/pt-br/windows/wsl/) para
|
||||
executar o FrankenPHP.
|
||||
|
||||
[Baixe o FrankenPHP](https://github.com/php/frankenphp/releases) ou copie esta
|
||||
linha no seu terminal para instalar automaticamente a versão apropriada para sua
|
||||
plataforma:
|
||||
|
||||
```console
|
||||
curl https://frankenphp.dev/install.sh | sh
|
||||
mv frankenphp /usr/local/bin/
|
||||
```
|
||||
|
||||
Para servir o conteúdo do diretório atual, execute:
|
||||
|
||||
```console
|
||||
frankenphp php-server
|
||||
```
|
||||
|
||||
Você também pode executar scripts de linha de comando com:
|
||||
|
||||
```console
|
||||
frankenphp php-cli /caminho/para/seu/script.php
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
Alternativamente, [imagens do Docker](docker.md) estão disponíveis:
|
||||
|
||||
```console
|
||||
docker run -v .:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Acesse `https://localhost` e divirta-se!
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Não tente usar `https://127.0.0.1`.
|
||||
> Use `https://localhost` e aceite o certificado autoassinado.
|
||||
> Use a
|
||||
> [variável de ambiente `SERVER_NAME`](config.md#variaveis-de-ambiente)
|
||||
> para alterar o domínio a ser usado.
|
||||
|
||||
### Homebrew
|
||||
|
||||
O FrankenPHP também está disponível como um pacote [Homebrew](https://brew.sh)
|
||||
para macOS e Linux.
|
||||
|
||||
Para instalá-lo:
|
||||
|
||||
```console
|
||||
brew install dunglas/frankenphp/frankenphp
|
||||
```
|
||||
|
||||
Para servir o conteúdo do diretório atual, execute:
|
||||
|
||||
```console
|
||||
frankenphp php-server
|
||||
```
|
||||
|
||||
## Documentação
|
||||
|
||||
- [Modo clássico](classic.md)
|
||||
- [Modo Worker](worker.md)
|
||||
- [Suporte a Early Hints (código de status HTTP 103)](early-hints.md)
|
||||
- [Tempo real](mercure.md)
|
||||
- [Servindo grandes arquivos estáticos com eficiência](x-sendfile.md)
|
||||
- [Configuração](config.md)
|
||||
- [Imagens Docker](docker.md)
|
||||
- [Implantação em produção](production.md)
|
||||
- [Otimização de desempenho](performance.md)
|
||||
- [Crie aplicações PHP **independentes** e autoexecutáveis](embed.md)
|
||||
- [Crie binários estáticos](static.md)
|
||||
- [Compile a partir do código-fonte](compile.md)
|
||||
- [Monitorando o FrankenPHP](metrics.md)
|
||||
- [Integração com Laravel](laravel.md)
|
||||
- [Problemas conhecidos](known-issues.md)
|
||||
- [Aplicação de demonstração (Symfony) e benchmarks](https://github.com/dunglas/frankenphp-demo)
|
||||
- [Documentação da biblioteca Go](https://pkg.go.dev/github.com/dunglas/frankenphp)
|
||||
- [Contribuindo e depurando](CONTRIBUTING.md)
|
||||
|
||||
## Exemplos e esqueletos
|
||||
|
||||
- [Symfony](https://github.com/dunglas/symfony-docker)
|
||||
- [API Platform](https://api-platform.com/docs/symfony)
|
||||
- [Laravel](laravel.md)
|
||||
- [Sulu](https://sulu.io/blog/running-sulu-with-frankenphp)
|
||||
- [WordPress](https://github.com/StephenMiracle/frankenwp)
|
||||
- [Drupal](https://github.com/dunglas/frankenphp-drupal)
|
||||
- [Joomla](https://github.com/alexandreelise/frankenphp-joomla)
|
||||
- [TYPO3](https://github.com/ochorocho/franken-typo3)
|
||||
- [Magento2](https://github.com/ekino/frankenphp-magento2)
|
||||
28
docs/pt-br/classic.md
Normal file
28
docs/pt-br/classic.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Usando o modo clássico
|
||||
|
||||
Sem nenhuma configuração adicional, o FrankenPHP opera no modo clássico.
|
||||
Neste modo, o FrankenPHP funciona como um servidor PHP tradicional, servindo
|
||||
diretamente arquivos PHP.
|
||||
Isso o torna um substituto perfeito para PHP-FPM ou Apache com mod_php.
|
||||
|
||||
Semelhante ao Caddy, o FrankenPHP aceita um número ilimitado de conexões e usa
|
||||
um [número fixo de threads](config.md#configuracao-do-caddyfile) para servi-las.
|
||||
O número de conexões aceitas e enfileiradas é limitado apenas pelos recursos
|
||||
disponíveis no sistema.
|
||||
O pool de threads do PHP opera com um número fixo de threads inicializadas na
|
||||
inicialização, comparável ao modo estático do PHP-FPM.
|
||||
Também é possível permitir que as threads
|
||||
[escalem automaticamente em tempo de execução](performance.md#max_threads),
|
||||
semelhante ao modo dinâmico do PHP-FPM.
|
||||
|
||||
As conexões enfileiradas aguardarão indefinidamente até que uma thread PHP
|
||||
esteja disponível para servi-las.
|
||||
Para evitar isso, você pode usar a
|
||||
[configuração](config.md#configuracao-do-caddyfile) `max_wait_time` para limitar
|
||||
o tempo que uma requisição pode esperar por uma thread PHP livre antes de ser
|
||||
rejeitada.
|
||||
Além disso, você pode definir um
|
||||
[tempo limite de escrita razoável no Caddy](https://caddyserver.com/docs/caddyfile/options#timeouts).
|
||||
|
||||
Cada instância do Caddy ativará apenas um pool de threads do FrankenPHP, que
|
||||
será compartilhado entre todos os blocos `php_server`.
|
||||
147
docs/pt-br/compile.md
Normal file
147
docs/pt-br/compile.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Compilar a partir dos fontes
|
||||
|
||||
Este documento explica como criar um binário FrankenPHP que carregará o PHP como
|
||||
uma biblioteca dinâmica.
|
||||
Este é o método recomendado.
|
||||
|
||||
Como alternativa, [compilações totalmente e principalmente estáticas](static.md)
|
||||
também podem ser criadas.
|
||||
|
||||
## Instalar o PHP
|
||||
|
||||
O FrankenPHP é compatível com PHP 8.2 e versões superiores.
|
||||
|
||||
### Com o Homebrew (Linux e Mac)
|
||||
|
||||
A maneira mais fácil de instalar uma versão da `libphp` compatível com o
|
||||
FrankenPHP é usar os pacotes ZTS fornecidos pelo
|
||||
[Homebrew PHP](https://github.com/shivammathur/homebrew-php).
|
||||
|
||||
Primeiro, se ainda não o fez, instale o [Homebrew](https://brew.sh).
|
||||
|
||||
Em seguida, instale a variante ZTS do PHP, o Brotli (opcional, para suporte à
|
||||
compressão) e o watcher (opcional, para detecção de alterações em arquivos):
|
||||
|
||||
```console
|
||||
brew install shivammathur/php/php-zts brotli watcher
|
||||
brew link --overwrite --force shivammathur/php/php-zts
|
||||
```
|
||||
|
||||
### Compilando o PHP
|
||||
|
||||
Alternativamente, você pode compilar o PHP a partir dos códigos-fonte com as
|
||||
opções necessárias para o FrankenPHP seguindo estes passos.
|
||||
|
||||
Primeiro, [obtenha os códigos-fonte do PHP](https://www.php.net/downloads.php) e
|
||||
extraia-os:
|
||||
|
||||
```console
|
||||
tar xf php-*
|
||||
cd php-*/
|
||||
```
|
||||
|
||||
Em seguida, execute o script `configure` com as opções necessárias para sua
|
||||
plataforma.
|
||||
As seguintes flags `./configure` são obrigatórias, mas você pode adicionar
|
||||
outras, por exemplo, para compilar extensões ou recursos adicionais.
|
||||
|
||||
#### Linux
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--enable-zend-max-execution-timers
|
||||
```
|
||||
|
||||
#### Mac
|
||||
|
||||
Use o gerenciador de pacotes [Homebrew](https://brew.sh/) para instalar as
|
||||
dependências necessárias e opcionais:
|
||||
|
||||
```console
|
||||
brew install libiconv bison brotli re2c pkg-config watcher
|
||||
echo 'export PATH="/opt/homebrew/opt/bison/bin:$PATH"' >> ~/.zshrc
|
||||
```
|
||||
|
||||
Em seguida, execute o script `configure`:
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--with-iconv=/opt/homebrew/opt/libiconv/
|
||||
```
|
||||
|
||||
#### Compilar o PHP
|
||||
|
||||
Finalmente, compile e instale o PHP:
|
||||
|
||||
```console
|
||||
make -j"$(getconf _NPROCESSORS_ONLN)"
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## Instalar dependências opcionais
|
||||
|
||||
Alguns recursos do FrankenPHP dependem de dependências opcionais do sistema que
|
||||
devem ser instaladas.
|
||||
Alternativamente, esses recursos podem ser desabilitados passando as tags de
|
||||
compilação para o compilador Go.
|
||||
|
||||
| Recurso | Dependência | Tag de compilação para desabilitá-lo |
|
||||
|----------------------------------------|-----------------------------------------------------------------------|--------------------------------------|
|
||||
| Compressão Brotli | [Brotli](https://github.com/google/brotli) | `nobrotli` |
|
||||
| Reiniciar workers ao alterar o arquivo | [Watcher C](https://github.com/e-dant/watcher/tree/release/watcher-c) | `nowatcher` |
|
||||
|
||||
## Compilando a aplicação Go
|
||||
|
||||
Agora você pode compilar o binário final.
|
||||
|
||||
### Usando o `xcaddy`
|
||||
|
||||
A maneira recomendada é usar o [`xcaddy`](https://github.com/caddyserver/xcaddy)
|
||||
para compilar o FrankenPHP.
|
||||
O `xcaddy` também permite adicionar facilmente
|
||||
[módulos Caddy personalizados](https://caddyserver.com/docs/modules/) e
|
||||
extensões FrankenPHP:
|
||||
|
||||
```console
|
||||
CGO_ENABLED=1 \
|
||||
XCADDY_GO_BUILD_FLAGS="-ldflags='-w -s' -tags=nobadger,nomysql,nopgx" \
|
||||
CGO_CFLAGS=$(php-config --includes) \
|
||||
CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" \
|
||||
xcaddy build \
|
||||
--output frankenphp \
|
||||
--with github.com/dunglas/frankenphp/caddy \
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Adicione módulos Caddy e extensões FrankenPHP extras aqui
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Se você estiver usando a `libc` `musl` (o padrão no Alpine Linux) e Symfony,
|
||||
> pode ser necessário aumentar o tamanho da pilha padrão.
|
||||
> Caso contrário, você poderá receber erros como `PHP Fatal error: Maximum call
|
||||
> stack size of 83360 bytes reached during compilation.
|
||||
> Try splitting expression`.
|
||||
>
|
||||
> Para fazer isso, altere a variável de ambiente `XCADDY_GO_BUILD_FLAGS` para
|
||||
> algo como
|
||||
> `XCADDY_GO_BUILD_FLAGS=$'-ldflags "-w -s -extldflags \'-Wl,-z,stack-size=0x80000\'"'`
|
||||
> (altere o valor do tamanho da pilha de acordo com as necessidades da sua
|
||||
> aplicação).
|
||||
|
||||
### Sem o `xcaddy`
|
||||
|
||||
Alternativamente, é possível compilar o FrankenPHP sem o `xcaddy` usando o
|
||||
comando `go` diretamente:
|
||||
|
||||
```console
|
||||
curl -L https://github.com/dunglas/frankenphp/archive/refs/heads/main.tar.gz | tar xz
|
||||
cd frankenphp-main/caddy/frankenphp
|
||||
CGO_CFLAGS=$(php-config --includes) CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" go build -tags=nobadger,nomysql,nopgx
|
||||
```
|
||||
320
docs/pt-br/config.md
Normal file
320
docs/pt-br/config.md
Normal file
@@ -0,0 +1,320 @@
|
||||
# Configuração
|
||||
|
||||
FrankenPHP, Caddy, bem como os módulos Mercure e Vulcain, podem ser configurados
|
||||
usando
|
||||
[os formatos suportados pelo Caddy](https://caddyserver.com/docs/getting-started#your-first-config).
|
||||
|
||||
Nas [imagens do Docker](docker.md), o `Caddyfile` está localizado em
|
||||
`/etc/frankenphp/Caddyfile`.
|
||||
O binário estático também procurará pelo `Caddyfile` no diretório onde o comando
|
||||
`frankenphp run` é executado.
|
||||
Você pode especificar um caminho personalizado com a opção `-c` ou `--config`.
|
||||
|
||||
O próprio PHP pode ser configurado
|
||||
[usando um arquivo `php.ini`](https://www.php.net/manual/pt_BR/configuration.file.php).
|
||||
|
||||
Dependendo do seu método de instalação, o interpretador PHP procurará por
|
||||
arquivos de configuração nos locais descritos acima.
|
||||
|
||||
## Docker
|
||||
|
||||
- `php.ini`: `/usr/local/etc/php/php.ini` (nenhum `php.ini` é fornecido por
|
||||
padrão)
|
||||
- Arquivos de configuração adicionais: `/usr/local/etc/php/conf.d/*.ini`
|
||||
- Extensões PHP: `/usr/local/lib/php/extensions/no-debug-zts-<YYYYMMDD>/`
|
||||
- Você deve copiar um template oficial fornecido pelo projeto PHP:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# Produção:
|
||||
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
|
||||
|
||||
# Ou desenvolvimento:
|
||||
RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini
|
||||
```
|
||||
|
||||
## Pacotes RPM e Debian
|
||||
|
||||
- `php.ini`: `/etc/frankenphp/php.ini` (um arquivo `php.ini` com configurações
|
||||
de produção é fornecido por padrão)
|
||||
- Arquivos de configuração adicionais: `/etc/frankenphp/php.d/*.ini`
|
||||
- Extensões PHP: `/usr/lib/frankenphp/modules/`
|
||||
|
||||
## Binário estático
|
||||
|
||||
- `php.ini`: O diretório no qual `frankenphp run` ou `frankenphp php-server` é
|
||||
executado e, em seguida, `/etc/frankenphp/php.ini`
|
||||
- Arquivos de configuração adicionais: `/etc/frankenphp/php.d/*.ini`
|
||||
- Extensões PHP: não podem ser carregadas, empacote-as no próprio binário
|
||||
- Copie um dos `php.ini-production` ou `php.ini-development` fornecidos
|
||||
[nos fontes do PHP](https://github.com/php/php-src/).
|
||||
|
||||
## Configuração do Caddyfile
|
||||
|
||||
As [diretivas HTTP](https://caddyserver.com/docs/caddyfile/concepts#directives)
|
||||
`php_server` ou `php` podem ser usadas dentro dos blocos de site para servir sua
|
||||
aplicação PHP.
|
||||
|
||||
Exemplo mínimo:
|
||||
|
||||
```caddyfile
|
||||
localhost {
|
||||
# Habilita compressão (opcional)
|
||||
encode zstd br gzip
|
||||
# Executa arquivos PHP no diretório atual e serve assets
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
Você também pode configurar explicitamente o FrankenPHP usando a opção global:
|
||||
A [opção global](https://caddyserver.com/docs/caddyfile/concepts#global-options)
|
||||
`frankenphp` pode ser usada para configurar o FrankenPHP.
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
num_threads <num_threads> # Define o número de threads PHP a serem iniciadas. Padrão: 2x o número de CPUs disponíveis.
|
||||
max_threads <num_threads> # Limita o número de threads PHP adicionais que podem ser iniciadas em tempo de execução. Padrão: num_threads. Pode ser definido como 'auto'.
|
||||
max_wait_time <duracao> # Define o tempo máximo que uma requisição pode esperar por uma thread PHP livre antes de atingir o tempo limite. Padrão: disabled.
|
||||
php_ini <chave> <valor> # Define uma diretiva php.ini. Pode ser usada várias vezes para definir múltiplas diretivas.
|
||||
worker {
|
||||
file <caminho> # Define o caminho para o script do worker.
|
||||
num <num> # Define o número de threads PHP a serem iniciadas, o padrão é 2x o número de CPUs disponíveis.
|
||||
env <chave> <valor> # Define uma variável de ambiente extra para o valor fornecido. Pode ser especificado mais de uma vez para múltiplas variáveis de ambiente.
|
||||
watch <caminho> # Define o caminho para monitorar alterações no arquivo. Pode ser especificado mais de uma vez para múltiplos caminhos.
|
||||
name <nome> # Define o nome do worker, usado em logs e métricas. Padrão: caminho absoluto do arquivo do worker.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Alternativamente, você pode usar a forma abreviada de uma linha da opção
|
||||
`worker`:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker <arquivo> <num>
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Você também pode definir vários workers se servir várias aplicações no mesmo
|
||||
servidor:
|
||||
|
||||
```caddyfile
|
||||
app.example.com {
|
||||
php_server {
|
||||
root /caminho/para/aplicacao/public
|
||||
worker index.php <num>
|
||||
}
|
||||
}
|
||||
|
||||
outra.example.com {
|
||||
php_server {
|
||||
root /caminho/para/outra/aplicacao/public
|
||||
worker index.php <num>
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Usar a diretiva `php_server` geralmente é o que você precisa, mas se precisar de
|
||||
controle total, você pode usar a diretiva `php` de mais baixo nível.
|
||||
A diretiva `php` passa toda a entrada para o PHP, em vez de primeiro verificar
|
||||
se é um arquivo PHP ou não.
|
||||
Leia mais sobre isso na [página de desempenho](performance.md#try_files).
|
||||
|
||||
Usar a diretiva `php_server` é equivalente a esta configuração:
|
||||
|
||||
```caddyfile
|
||||
route {
|
||||
# Adiciona barra final para requisições de diretório
|
||||
@canonicalPath {
|
||||
file {path}/index.php
|
||||
not path */
|
||||
}
|
||||
redir @canonicalPath {path}/ 308
|
||||
# Se o arquivo requisitado não existir, tenta os arquivos index
|
||||
@indexFiles file {
|
||||
try_files {path} {path}/index.php index.php
|
||||
split_path .php
|
||||
}
|
||||
rewrite @indexFiles {http.matchers.file.relative}
|
||||
|
||||
# FrankenPHP!
|
||||
@phpFiles path *.php
|
||||
php @phpFiles
|
||||
file_server
|
||||
}
|
||||
```
|
||||
|
||||
As diretivas `php_server` e `php` têm as seguintes opções:
|
||||
|
||||
```caddyfile
|
||||
php_server [<matcher>] {
|
||||
root <directory> # Define a pasta raiz para o site. Padrão: diretiva `root`.
|
||||
split_path <delim...> # Define as substrings para dividir o URI em duas partes. A primeira substring correspondente será usada para separar as "informações de caminho" do caminho. A primeira parte é sufixada com a substring correspondente e será assumida como o nome real do recurso (script CGI). A segunda parte será definida como PATH_INFO para o script usar. Padrão: `.php`
|
||||
resolve_root_symlink false # Desabilita a resolução do diretório `root` para seu valor real avaliando um link simbólico, se houver (habilitado por padrão).
|
||||
env <chave> <valor> # Define uma variável de ambiente extra para o valor fornecido. Pode ser especificado mais de uma vez para múltiplas variáveis de ambiente.
|
||||
file_server off # Desabilita a diretiva interna file_server.
|
||||
worker { # Cria um worker específico para este servidor. Pode ser especificado mais de uma vez para múltiplos workers.
|
||||
file <caminho> # Define o caminho para o script do worker, pode ser relativo à raiz do php_server
|
||||
num <num> # Define o número de threads PHP a serem iniciadas, o padrão é 2x o número de threads disponíveis
|
||||
name <nome> # Define o nome do worker, usado em logs e métricas. Padrão: caminho absoluto do arquivo do worker. Sempre começa com m# quando definido em um bloco php_server.
|
||||
watch <caminho> # Define o caminho para monitorar alterações no arquivo. Pode ser especificado mais de uma vez para múltiplos caminhos.
|
||||
env <chave> <valor> # Define uma variável de ambiente extra para o valor fornecido. Pode ser especificado mais de uma vez para múltiplas variáveis de ambiente. As variáveis de ambiente para este worker também são herdadas do php_server pai, mas podem ser sobrescritas aqui.
|
||||
}
|
||||
worker <outro_arquivo> <num> # Também pode usar a forma abreviada, como no bloco global frankenphp.
|
||||
}
|
||||
```
|
||||
|
||||
### Monitorando alterações em arquivos
|
||||
|
||||
Como os workers inicializam sua aplicação apenas uma vez e a mantêm na memória,
|
||||
quaisquer alterações nos seus arquivos PHP não serão refletidas imediatamente.
|
||||
|
||||
Os workers podem ser reiniciados em caso de alterações nos arquivos por meio da
|
||||
diretiva `watch`.
|
||||
Isso é útil para ambientes de desenvolvimento.
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker {
|
||||
file /caminho/para/aplicacao/public/worker.php
|
||||
watch
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Se o diretório `watch` não for especificado, ele usará o valor padrão
|
||||
`./**/*.{php,yaml,yml,twig,env}`,
|
||||
que monitora todos os arquivos `.php`, `.yaml`, `.yml`, `.twig` e `.env` no
|
||||
diretório e subdiretórios onde o processo FrankenPHP foi iniciado.
|
||||
Você também pode especificar um ou mais diretórios por meio de um
|
||||
[padrão de nome de arquivo shell](https://pkg.go.dev/path/filepath#Match):
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker {
|
||||
file /caminho/para/aplicacao/public/worker.php
|
||||
watch /caminho/para/aplicacao # monitora todos os arquivos em todos os subdiretórios de /caminho/para/aplicacao
|
||||
watch /caminho/para/aplicacao/*.php # monitora arquivos terminados em .php em /caminho/para/aplicacao
|
||||
watch /caminho/para/aplicacao/**/*.php # monitora arquivos PHP em /caminho/para/aplicacao e subdiretórios
|
||||
watch /caminho/para/aplicacao/**/*.{php,twig} # monitora arquivos PHP e Twig em /caminho/para/aplicacao e subdiretórios
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- O padrão `**` significa monitoramento recursivo
|
||||
- Diretórios também podem ser relativos (ao local de início do processo
|
||||
FrankenPHP)
|
||||
- Se você tiver vários workers definidos, todos eles serão reiniciados quando um
|
||||
arquivo for alterado
|
||||
- Tenha cuidado ao monitorar arquivos criados em tempo de execução (como logs),
|
||||
pois eles podem causar reinicializações indesejadas de workers.
|
||||
|
||||
O monitor de arquivos é baseado em
|
||||
[e-dant/watcher](https://github.com/e-dant/watcher).
|
||||
|
||||
### Full Duplex (HTTP/1)
|
||||
|
||||
Ao usar HTTP/1.x, pode ser desejável habilitar o modo full-duplex para permitir
|
||||
a gravação de uma resposta antes que todo o corpo tenha sido lido.
|
||||
(por exemplo: WebSocket, Server-Sent Events, etc.)
|
||||
|
||||
Esta é uma configuração opcional que precisa ser adicionada às opções globais no
|
||||
`Caddyfile`:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
servers {
|
||||
enable_full_duplex
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Habilitar esta opção pode causar deadlock em clientes HTTP/1.x antigos que não
|
||||
> suportam full-duplex.
|
||||
> Isso também pode ser configurado usando a configuração de ambiente
|
||||
> `CADDY_GLOBAL_OPTIONS`:
|
||||
|
||||
```sh
|
||||
CADDY_GLOBAL_OPTIONS="servers {
|
||||
enable_full_duplex
|
||||
}"
|
||||
```
|
||||
|
||||
Você pode encontrar mais informações sobre esta configuração na
|
||||
[documentação do Caddy](https://caddyserver.com/docs/caddyfile/options#enable-full-duplex).
|
||||
|
||||
## Variáveis de ambiente
|
||||
|
||||
As seguintes variáveis de ambiente podem ser usadas para injetar diretivas Caddy
|
||||
no `Caddyfile` sem modificá-lo:
|
||||
|
||||
- `SERVER_NAME`: altera
|
||||
[os endereços nos quais escutar](https://caddyserver.com/docs/caddyfile/concepts#addresses),
|
||||
os nomes de host fornecidos também serão usados para o certificado TLS gerado.
|
||||
- `SERVER_ROOT`: altera o diretório raiz do site, o padrão é `public/`.
|
||||
- `CADDY_GLOBAL_OPTIONS`: injeta
|
||||
[opções globais](https://caddyserver.com/docs/caddyfile/options).
|
||||
- `FRANKENPHP_CONFIG`: injeta a configuração sob a diretiva `frankenphp`.
|
||||
|
||||
Quanto às SAPIs FPM e CLI, as variáveis de ambiente são expostas por padrão na
|
||||
superglobal `$_SERVER`.
|
||||
|
||||
O valor `S` da
|
||||
[diretiva `variables_order` do PHP](https://www.php.net/manual/pt_BR/ini.core.php#ini.variables-order)
|
||||
é sempre equivalente a `ES`, independentemente da colocação de `E` em outra
|
||||
parte desta diretiva.
|
||||
|
||||
## Configuração do PHP
|
||||
|
||||
Para carregar
|
||||
[arquivos de configuração adicionais do PHP](https://www.php.net/manual/pt_BR/configuration.file.php#configuration.file.scan),
|
||||
a variável de ambiente `PHP_INI_SCAN_DIR` pode ser usada.
|
||||
Quando definida, o PHP carregará todos os arquivos com a extensão `.ini`
|
||||
presentes nos diretórios fornecidos.
|
||||
|
||||
Você também pode alterar a configuração do PHP usando a diretiva `php_ini` no
|
||||
`Caddyfile`:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
php_ini memory_limit 256M
|
||||
|
||||
# ou
|
||||
|
||||
php_ini {
|
||||
memory_limit 256M
|
||||
max_execution_time 15
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Habilitar o modo de depuração
|
||||
|
||||
Ao usar a imagem do Docker, defina a variável de ambiente `CADDY_GLOBAL_OPTIONS`
|
||||
como `debug` para habilitar o modo de depuração:
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public \
|
||||
-e CADDY_GLOBAL_OPTIONS=debug \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
232
docs/pt-br/docker.md
Normal file
232
docs/pt-br/docker.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# Construindo uma imagem Docker personalizada
|
||||
|
||||
[As imagens Docker do FrankenPHP](https://hub.docker.com/r/dunglas/frankenphp)
|
||||
são baseadas em [imagens oficiais do PHP](https://hub.docker.com/_/php/).
|
||||
Variantes do Debian e do Alpine Linux são fornecidas para arquiteturas
|
||||
populares.
|
||||
Variantes do Debian são recomendadas.
|
||||
|
||||
Variantes para PHP 8.2, 8.3 e 8.4 são fornecidas.
|
||||
|
||||
As tags seguem este padrão:
|
||||
`dunglas/frankenphp:<versao-do-frankenphp>-php<versao-do-php>-<so>`.
|
||||
|
||||
- `<versao-do-frankenphp>` e `<versao-do-php>` são números de versão do
|
||||
FrankenPHP e do PHP, respectivamente, variando de maior (ex.: `1`), menor
|
||||
(ex.: `1.2`) a versões de patch (ex.: `1.2.3`).
|
||||
- `<so>` é `bookworm` (para Debian Bookworm) ou `alpine` (para a versão estável
|
||||
mais recente do Alpine).
|
||||
|
||||
[Navegue pelas tags](https://hub.docker.com/r/dunglas/frankenphp/tags).
|
||||
|
||||
## Como usar as imagens
|
||||
|
||||
Crie um `Dockerfile` no seu projeto:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
COPY . /app/public
|
||||
```
|
||||
|
||||
Em seguida, execute estes comandos para compilar e executar a imagem do Docker:
|
||||
|
||||
```console
|
||||
docker build -t minha-app-php .
|
||||
docker run -it --rm --name minha-app-rodando minha-app-php
|
||||
```
|
||||
|
||||
## Como instalar mais extensões PHP
|
||||
|
||||
O script
|
||||
[`docker-php-extension-installer`](https://github.com/mlocati/docker-php-extension-installer)
|
||||
é fornecido na imagem base.
|
||||
Adicionar extensões PHP adicionais é simples:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# adicione extensões adicionais aqui:
|
||||
RUN install-php-extensions \
|
||||
pdo_mysql \
|
||||
gd \
|
||||
intl \
|
||||
zip \
|
||||
opcache
|
||||
```
|
||||
|
||||
## Como instalar mais módulos do Caddy
|
||||
|
||||
O FrankenPHP é construído sobre o Caddy, e todos os
|
||||
[módulos do Caddy](https://caddyserver.com/docs/modules/) podem ser usados com o
|
||||
FrankenPHP.
|
||||
|
||||
A maneira mais fácil de instalar módulos personalizados do Caddy é usar o
|
||||
[xcaddy](https://github.com/caddyserver/xcaddy):
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp:builder AS builder
|
||||
|
||||
# Copia o xcaddy para a imagem do builder
|
||||
COPY --from=caddy:builder /usr/bin/xcaddy /usr/bin/xcaddy
|
||||
|
||||
# O CGO precisa estar habilitado para compilar o FrankenPHP
|
||||
RUN CGO_ENABLED=1 \
|
||||
XCADDY_SETCAP=1 \
|
||||
XCADDY_GO_BUILD_FLAGS="-ldflags='-w -s' -tags=nobadger,nomysql,nopgx" \
|
||||
CGO_CFLAGS=$(php-config --includes) \
|
||||
CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" \
|
||||
xcaddy build \
|
||||
--output /usr/local/bin/frankenphp \
|
||||
--with github.com/dunglas/frankenphp=./ \
|
||||
--with github.com/dunglas/frankenphp/caddy=./caddy/ \
|
||||
--with github.com/dunglas/caddy-cbrotli \
|
||||
# Mercure e Vulcain estão incluídos na compilação oficial, mas sinta-se
|
||||
# à vontade para removê-los
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Adicione módulos Caddy extras aqui
|
||||
|
||||
FROM dunglas/frankenphp AS runner
|
||||
|
||||
# Substitui o binário oficial pelo que contém seus módulos personalizados
|
||||
COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
|
||||
```
|
||||
|
||||
A imagem `builder` fornecida pelo FrankenPHP contém uma versão compilada de
|
||||
`libphp`.
|
||||
[Imagens de builder](https://hub.docker.com/r/dunglas/frankenphp/tags?name=builder)
|
||||
são fornecidas para todas as versões do FrankenPHP e PHP, tanto para Debian
|
||||
quanto para Alpine.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Se você estiver usando Alpine Linux e Symfony, pode ser necessário
|
||||
> [aumentar o tamanho padrão da pilha](compile.md#using-xcaddy).
|
||||
|
||||
## Habilitando o modo worker por padrão
|
||||
|
||||
Defina a variável de ambiente `FRANKENPHP_CONFIG` para iniciar o FrankenPHP com
|
||||
um worker script:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# ...
|
||||
|
||||
ENV FRANKENPHP_CONFIG="worker ./public/index.php"
|
||||
```
|
||||
|
||||
## Usando um volume em desenvolvimento
|
||||
|
||||
Para desenvolver facilmente com o FrankenPHP, monte o diretório do seu host que
|
||||
contém o código-fonte da aplicação como um volume no contêiner Docker:
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public -p 80:80 -p 443:443 -p 443:443/udp --tty minha-app-php
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> A opção `--tty` permite ter logs legíveis por humanos em vez de logs JSON.
|
||||
|
||||
Com o Docker Compose:
|
||||
|
||||
```yaml
|
||||
# compose.yaml
|
||||
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
# Descomente a linha a seguir se quiser usar um Dockerfile personalizado
|
||||
#build: .
|
||||
# Descomente a linha a seguir se quiser executar isso em um ambiente de
|
||||
# produção
|
||||
# restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- ./:/app/public
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
# Comente a linha a seguir em produção, isso permite ter logs legíveis em
|
||||
# desenvolvimento
|
||||
tty: true
|
||||
|
||||
# Volumes necessários para certificados e configuração do Caddy
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
## Executando como um usuário não root
|
||||
|
||||
O FrankenPHP pode ser executado como um usuário não root no Docker.
|
||||
|
||||
Aqui está um exemplo de `Dockerfile` fazendo isso:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
ARG USER=appuser
|
||||
|
||||
RUN \
|
||||
# Use "adduser -D ${USER}" para distribuições baseadas em Alpine
|
||||
useradd ${USER}; \
|
||||
# Adiciona capacidade adicional para vincular às portas 80 e 443
|
||||
setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp; \
|
||||
# Concede acesso de escrita a /data/caddy e /config/caddy
|
||||
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy
|
||||
|
||||
USER ${USER}
|
||||
```
|
||||
|
||||
### Executando sem capacidades adicionais
|
||||
|
||||
Mesmo executando sem root, o FrankenPHP precisa do recurso
|
||||
`CAP_NET_BIND_SERVICE` para vincular o servidor web em portas privilegiadas (80
|
||||
e 443).
|
||||
|
||||
Se você expor o FrankenPHP em uma porta não privilegiada (1024 e acima), é
|
||||
possível executar o servidor web como um usuário não root e sem a necessidade de
|
||||
nenhuma capacidade adicional:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
ARG USER=appuser
|
||||
|
||||
RUN \
|
||||
# Use "adduser -D ${USER}" para distribuições baseadas em Alpine
|
||||
useradd ${USER}; \
|
||||
# Remove a capacidade padrão
|
||||
setcap -r /usr/local/bin/frankenphp; \
|
||||
# Concede acesso de escrita a /data/caddy e /config/caddy
|
||||
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy
|
||||
|
||||
USER ${USER}
|
||||
```
|
||||
|
||||
Em seguida, defina a variável de ambiente `SERVER_NAME` para usar uma porta sem
|
||||
privilégios.
|
||||
Exemplo: `:8000`
|
||||
|
||||
## Atualizações
|
||||
|
||||
As imagens do Docker são compiladas:
|
||||
|
||||
- quando uma tag de uma nova versão é criada.
|
||||
- diariamente às 4h UTC, se novas versões das imagens oficiais do PHP estiverem
|
||||
disponíveis.
|
||||
|
||||
## Versões de desenvolvimento
|
||||
|
||||
As versões de desenvolvimento estão disponíveis no repositório Docker
|
||||
[`dunglas/frankenphp-dev`](https://hub.docker.com/repository/docker/dunglas/frankenphp-dev).
|
||||
Uma nova compilação é acionada sempre que um commit é enviado para o branch
|
||||
principal do repositório do GitHub.
|
||||
|
||||
As tags `latest*` apontam para o HEAD do branch `main`.
|
||||
Tags no formato `sha-<git-commit-hash>` também estão disponíveis.
|
||||
24
docs/pt-br/early-hints.md
Normal file
24
docs/pt-br/early-hints.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Early Hints
|
||||
|
||||
O FrankenPHP suporta nativamente o
|
||||
[código de status 103 Early Hints](https://developer.chrome.com/blog/early-hints/).
|
||||
Usar Early Hints pode melhorar o tempo de carregamento das suas páginas web em
|
||||
30%.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
header('Link: </style.css>; rel=preload; as=style');
|
||||
headers_send(103);
|
||||
|
||||
// seus algoritmos e consultas SQL lentos 🤪
|
||||
|
||||
echo <<<'HTML'
|
||||
<!DOCTYPE html>
|
||||
<title>Olá FrankenPHP</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
HTML;
|
||||
```
|
||||
|
||||
As Early Hints são suportadas tanto pelo modo normal quanto pelo modo
|
||||
[worker](worker.md).
|
||||
166
docs/pt-br/embed.md
Normal file
166
docs/pt-br/embed.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# Aplicações PHP como binários independentes
|
||||
|
||||
O FrankenPHP tem a capacidade de incorporar o código-fonte e os recursos de
|
||||
aplicações PHP em um binário estático e independente.
|
||||
|
||||
Graças a esse recurso, aplicações PHP podem ser distribuídas como binários
|
||||
independentes que incluem a própria aplicação, o interpretador PHP e o Caddy, um
|
||||
servidor web de nível de produção.
|
||||
|
||||
Saiba mais sobre esse recurso
|
||||
[na apresentação feita por Kévin na SymfonyCon 2023](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/).
|
||||
|
||||
Para incorporar aplicações Laravel,
|
||||
[leia esta entrada específica na documentação](laravel.md#laravel-apps-as-standalone-binaries).
|
||||
|
||||
## Preparando sua aplicação
|
||||
|
||||
Antes de criar o binário independente, certifique-se de que sua aplicação esteja
|
||||
pronta para ser incorporada.
|
||||
|
||||
Por exemplo, você provavelmente deseja:
|
||||
|
||||
- Instalar as dependências de produção da aplicação.
|
||||
- Fazer o dump do carregador automático.
|
||||
- Habilitar o modo de produção da sua aplicação (se houver).
|
||||
- Remover arquivos desnecessários, como `.git` ou testes, para reduzir o tamanho
|
||||
do seu binário final.
|
||||
|
||||
Por exemplo, para uma aplicação Symfony, você pode usar os seguintes comandos:
|
||||
|
||||
```console
|
||||
# Exporta o projeto para se livrar de .git/, etc.
|
||||
mkdir $TMPDIR/minha-aplicacao-preparada
|
||||
git archive HEAD | tar -x -C $TMPDIR/minha-aplicacao-preparada
|
||||
cd $TMPDIR/minha-aplicacao-preparada
|
||||
|
||||
# Define as variáveis de ambiente adequadas
|
||||
echo APP_ENV=prod > .env.local
|
||||
echo APP_DEBUG=0 >> .env.local
|
||||
|
||||
# Remove os testes e outros arquivos desnecessários para economizar espaço.
|
||||
# Como alternativa, adicione esses arquivos com o atributo export-ignore no seu
|
||||
# arquivo .gitattributes.
|
||||
rm -Rf tests/
|
||||
|
||||
# Instala as dependências
|
||||
composer install --ignore-platform-reqs --no-dev -a
|
||||
|
||||
# Otimiza o arquivo .env
|
||||
composer dump-env prod
|
||||
```
|
||||
|
||||
### Personalizando a configuração
|
||||
|
||||
Para personalizar
|
||||
[a configuração](config.md), você pode colocar um arquivo `Caddyfile` e um
|
||||
arquivo `php.ini` no diretório principal da aplicação a ser incorporada
|
||||
(`$TMPDIR/minha-aplicacao-preparada` no exemplo anterior).
|
||||
|
||||
## Criando um binário do Linux
|
||||
|
||||
A maneira mais fácil de criar um binário do Linux é usar o builder baseado em
|
||||
Docker que fornecemos.
|
||||
|
||||
1. Crie um arquivo chamado `static-build.Dockerfile` no repositório da sua
|
||||
aplicação:
|
||||
|
||||
```dockerfile
|
||||
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder
|
||||
|
||||
# Copia sua aplicação
|
||||
WORKDIR /go/src/app/dist/app
|
||||
COPY . .
|
||||
|
||||
# Compila o binário estático
|
||||
WORKDIR /go/src/app/
|
||||
RUN EMBED=dist/app/ ./build-static.sh
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Alguns arquivos `.dockerignore` (por exemplo, o
|
||||
> [`.dockerignore` padrão do Docker do Symfony](https://github.com/dunglas/symfony-docker/blob/main/.dockerignore))
|
||||
> ignorarão o diretório `vendor/` e os arquivos `.env`.
|
||||
> Certifique-se de ajustar ou remover o arquivo `.dockerignore` antes da
|
||||
> compilação.
|
||||
|
||||
2. Construa:
|
||||
|
||||
```console
|
||||
docker build -t aplicacao-estatica -f static-build.Dockerfile .
|
||||
```
|
||||
|
||||
3. Extraia o binário:
|
||||
|
||||
```console
|
||||
docker cp $(docker create --name aplicacao-estatica-tmp aplicacao-estatica):/go/src/app/dist/frankenphp-linux-x86_64 minha-aplicacao ; docker rm aplicacao-estatica-tmp
|
||||
```
|
||||
|
||||
O binário resultante é o arquivo `minha-aplicacao` no diretório atual.
|
||||
|
||||
## Criando um binário para outros sistemas operacionais
|
||||
|
||||
Se você não quiser usar o Docker ou quiser compilar um binário para macOS, use o
|
||||
script de shell que fornecemos:
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
EMBED=/caminho/para/sua/aplicacao ./build-static.sh
|
||||
```
|
||||
|
||||
O binário resultante é o arquivo `frankenphp-<os>-<arch>` no diretório `dist/`.
|
||||
|
||||
## Usando o binário
|
||||
|
||||
É isso! O arquivo `minha-aplicacao` (ou `dist/frankenphp-<os>-<arch>` em outros
|
||||
sistemas operacionais) contém sua aplicação independente!
|
||||
|
||||
Para iniciar a aplicação web, execute:
|
||||
|
||||
```console
|
||||
./minha-aplicacao php-server
|
||||
```
|
||||
|
||||
Se a sua aplicação contiver um [worker script](worker.md), inicie o worker com
|
||||
algo como:
|
||||
|
||||
```console
|
||||
./minha-aplicacao php-server --worker public/index.php
|
||||
```
|
||||
|
||||
Para habilitar HTTPS (um certificado Let's Encrypt é criado automaticamente),
|
||||
HTTP/2 e HTTP/3, especifique o nome de domínio a ser usado:
|
||||
|
||||
```console
|
||||
./minha-aplicacao php-server --domain localhost
|
||||
```
|
||||
|
||||
Você também pode executar os scripts PHP CLI incorporados ao seu binário:
|
||||
|
||||
```console
|
||||
./minha-aplicacao php-cli bin/console
|
||||
```
|
||||
|
||||
## Extensões PHP
|
||||
|
||||
Por padrão, o script criará as extensões requeridas pelo arquivo `composer.json`
|
||||
do seu projeto, se houver.
|
||||
Se o arquivo `composer.json` não existir, as extensões padrão serão compiladas,
|
||||
conforme documentado na [entrada de compilações estáticas](static.md).
|
||||
|
||||
Para personalizar as extensões, use a variável de ambiente `PHP_EXTENSIONS`.
|
||||
|
||||
## Personalizando a compilação
|
||||
|
||||
[Leia a documentação da compilação estática](static.md) para ver como
|
||||
personalizar o binário (extensões, versão do PHP...).
|
||||
|
||||
## Distribuindo o binário
|
||||
|
||||
No Linux, o binário criado é compactado usando [UPX](https://upx.github.io).
|
||||
|
||||
No Mac, para reduzir o tamanho do arquivo antes de enviá-lo, você pode
|
||||
compactá-lo.
|
||||
Recomendamos usar `xz`.
|
||||
39
docs/pt-br/github-actions.md
Normal file
39
docs/pt-br/github-actions.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Usando GitHub Actions
|
||||
|
||||
Este repositório constrói e implementa a imagem do Docker no
|
||||
[Docker Hub](https://hub.docker.com/r/dunglas/frankenphp) em cada pull request
|
||||
aprovado ou em seu próprio fork após a configuração.
|
||||
|
||||
## Configurando GitHub Actions
|
||||
|
||||
Nas configurações do repositório, em "Secrets", adicione os seguintes segredos:
|
||||
|
||||
- `REGISTRY_LOGIN_SERVER`: O registro do Docker a ser usado (por exemplo,
|
||||
`docker.io`).
|
||||
- `REGISTRY_USERNAME`: O nome de usuário a ser usado para fazer login no
|
||||
registro (por exemplo, `dunglas`).
|
||||
- `REGISTRY_PASSWORD`: A senha a ser usada para fazer login no registro (por
|
||||
exemplo, uma chave de acesso).
|
||||
- `IMAGE_NAME`: O nome da imagem (por exemplo, `dunglas/frankenphp`).
|
||||
|
||||
## Construindo e enviando a imagem
|
||||
|
||||
1. Crie um pull request ou faça o push para o seu fork.
|
||||
2. O GitHub Actions construirá a imagem e executará os testes.
|
||||
3. Se a construção for bem-sucedida, a imagem será enviada para o registro
|
||||
usando a tag `pr-x`, onde `x` é o número do PR.
|
||||
|
||||
## Implantando a imagem
|
||||
|
||||
1. Após o merge do pull request, o GitHub Actions executará os testes novamente
|
||||
e criará uma nova imagem.
|
||||
2. Se a construção for bem-sucedida, a tag `main` será atualizada no registro do
|
||||
Docker.
|
||||
|
||||
## Versões
|
||||
|
||||
1. Crie uma nova tag no repositório.
|
||||
2. O GitHub Actions construirá a imagem e executará os testes.
|
||||
3. Se a construção for bem-sucedida, a imagem será enviada para o registro
|
||||
usando o nome da tag como tag (por exemplo, `v1.2.3` e `v1.2` serão criadas).
|
||||
4. A tag `latest` também será atualizada.
|
||||
185
docs/pt-br/known-issues.md
Normal file
185
docs/pt-br/known-issues.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Problemas conhecidos
|
||||
|
||||
## Extensões PHP não suportadas
|
||||
|
||||
As seguintes extensões são conhecidas por não serem compatíveis com o
|
||||
FrankenPHP:
|
||||
|
||||
| Nome | Motivo | Alternativas |
|
||||
|-------------------------------------------------------------------------------------------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------|
|
||||
| [imap](https://www.php.net/manual/pt_BR/imap.installation.php) | Não é thread-safe | [javanile/php-imap2](https://github.com/javanile/php-imap2), [webklex/php-imap](https://github.com/Webklex/php-imap) |
|
||||
| [newrelic](https://docs.newrelic.com/docs/apm/agents/php-agent/getting-started/introduction-new-relic-php/) | Não é thread-safe | - |
|
||||
|
||||
## Extensões PHP com falhas
|
||||
|
||||
As seguintes extensões apresentam falhas conhecidas e comportamentos inesperados
|
||||
quando usadas com o FrankenPHP:
|
||||
|
||||
| Nome | Problema |
|
||||
|------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [ext-openssl](https://www.php.net/manual/pt_BR/book.openssl.php) | Ao usar uma versão estática do FrankenPHP (compilada com a `libc` `musl`), a extensão OpenSSL pode quebrar sob cargas pesadas. Uma solução alternativa é usar uma versão vinculada dinamicamente (como a usada em imagens Docker). Esta falha está [sendo monitorada pelo PHP](https://github.com/php/php-src/issues/13648) |
|
||||
|
||||
## `get_browser`
|
||||
|
||||
A função
|
||||
[`get_browser()`](https://www.php.net/manual/pt_BR/function.get-browser.php)
|
||||
parece apresentar mau desempenho após algum tempo.
|
||||
Uma solução alternativa é armazenar em cache (por exemplo, com
|
||||
[APCu](https://www.php.net/manual/pt_BR/book.apcu.php)) os resultados por Agente
|
||||
de Usuário, pois são estáticos.
|
||||
|
||||
## Imagens Docker binárias independentes e baseadas em Alpine
|
||||
|
||||
As imagens Docker binárias independentes e baseadas em Alpine
|
||||
(`dunglas/frankenphp:*-alpine`) usam a [`libc` `musl`](https://musl.libc.org/)
|
||||
em vez de [`glibc` e similares](https://www.etalabs.net/compare_libcs.html) para
|
||||
manter um tamanho binário menor.
|
||||
Isso pode levar a alguns problemas de compatibilidade.
|
||||
Em particular, o sinalizador glob `GLOB_BRACE`
|
||||
[não está disponível](https://www.php.net/manual/pt_BR/function.glob.php)
|
||||
|
||||
## Usando `https://127.0.0.1` com o Docker
|
||||
|
||||
Por padrão, o FrankenPHP gera um certificado TLS para `localhost`.
|
||||
É a opção mais fácil e recomendada para desenvolvimento local.
|
||||
|
||||
Se você realmente deseja usar `127.0.0.1` como host, é possível configurá-lo
|
||||
para gerar um certificado definindo o nome do servidor como `127.0.0.1`.
|
||||
|
||||
Infelizmente, isso não é suficiente ao usar o Docker devido ao
|
||||
[seu sistema de rede](https://docs.docker.com/network/).
|
||||
Você receberá um erro TLS semelhante a
|
||||
`curl: (35) LibreSSL/3.3.6: erro:1404B438:SSL routines:ST_CONNECT:tlsv1 alert internal error`.
|
||||
|
||||
Se você estiver usando Linux, uma solução é usar
|
||||
[o driver de rede do host](https://docs.docker.com/network/network-tutorial-host/):
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
--network host \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
O driver de rede do host não é compatível com Mac e Windows.
|
||||
Nessas plataformas, você terá que descobrir o endereço IP do contêiner e
|
||||
incluí-lo nos nomes dos servidores.
|
||||
|
||||
Execute o comando `docker network inspect bridge` e verifique a chave
|
||||
`Containers` para identificar o último endereço IP atribuído atualmente sob a
|
||||
chave `IPv4Address` e incremente-o em um.
|
||||
Se nenhum contêiner estiver em execução, o primeiro endereço IP atribuído
|
||||
geralmente é `172.17.0.2`.
|
||||
|
||||
Em seguida, inclua isso na variável de ambiente `SERVER_NAME`:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1, 172.17.0.3" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Certifique-se de substituir `172.17.0.3` pelo IP que será atribuído ao seu
|
||||
> contêiner.
|
||||
|
||||
Agora você deve conseguir acessar `https://127.0.0.1` a partir da máquina host.
|
||||
|
||||
Se este não for o caso, inicie o FrankenPHP em modo de depuração para tentar
|
||||
descobrir o problema:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e CADDY_GLOBAL_OPTIONS="debug" \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
## Scripts do Composer que referenciam `@php`
|
||||
|
||||
[Scripts do Composer](https://getcomposer.org/doc/articles/scripts.md) podem
|
||||
querer executar um binário PHP para algumas tarefas, por exemplo, em
|
||||
[um projeto Laravel](laravel.md) para executar
|
||||
`@php artisan package:discover --ansi`.
|
||||
Isso
|
||||
[atualmente falha](https://github.com/dunglas/frankenphp/issues/483#issuecomment-1899890915)
|
||||
por dois motivos:
|
||||
|
||||
- O Composer não sabe como chamar o binário do FrankenPHP;
|
||||
- O Composer pode adicionar configurações do PHP usando a flag `-d` no comando,
|
||||
que o FrankenPHP ainda não suporta.
|
||||
|
||||
Como solução alternativa, podemos criar um script de shell em
|
||||
`/usr/local/bin/php` que remove os parâmetros não suportados e, em seguida,
|
||||
chama o FrankenPHP:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
args=("$@")
|
||||
index=0
|
||||
for i in "$@"
|
||||
do
|
||||
if [ "$i" == "-d" ]; then
|
||||
unset 'args[$index]'
|
||||
unset 'args[$index+1]'
|
||||
fi
|
||||
index=$((index+1))
|
||||
done
|
||||
|
||||
/usr/local/bin/frankenphp php-cli ${args[@]}
|
||||
```
|
||||
|
||||
Em seguida, defina a variável de ambiente `PHP_BINARY` para o caminho do nosso
|
||||
script `php` e execute o Composer:
|
||||
|
||||
```console
|
||||
export PHP_BINARY=/usr/local/bin/php
|
||||
composer install
|
||||
```
|
||||
|
||||
## Solução de problemas de TLS/SSL com binários estáticos
|
||||
|
||||
Ao usar binários estáticos, você pode encontrar os seguintes erros relacionados
|
||||
a TLS, por exemplo, ao enviar emails usando STARTTLS:
|
||||
|
||||
```text
|
||||
Unable to connect with STARTTLS: stream_socket_enable_crypto(): SSL operation failed with code 5. OpenSSL Error messages:
|
||||
error:80000002:system library::No such file or directory
|
||||
error:80000002:system library::No such file or directory
|
||||
error:80000002:system library::No such file or directory
|
||||
error:0A000086:SSL routines::certificate verify failed
|
||||
```
|
||||
|
||||
Como o binário estático não empacota certificados TLS, você precisa apontar o
|
||||
OpenSSL para a instalação local de certificados de CA.
|
||||
|
||||
Inspecione a saída de
|
||||
[`openssl_get_cert_locations()`](https://www.php.net/manual/pt_BR/function.openssl-get-cert-locations.php),
|
||||
para descobrir onde os certificados de CA devem ser instalados e armazene-os
|
||||
neste local.
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Contextos web e CLI podem ter configurações diferentes.
|
||||
> Certifique-se de executar `openssl_get_cert_locations()` no contexto
|
||||
> apropriado.
|
||||
|
||||
[Certificados CA extraídos do Mozilla podem ser baixados no site do curl](https://curl.se/docs/caextract.html).
|
||||
|
||||
Como alternativa, muitas distribuições, incluindo Debian, Ubuntu e Alpine,
|
||||
fornecem pacotes chamados `ca-certificates` que contêm esses certificados.
|
||||
|
||||
Também é possível usar `SSL_CERT_FILE` e `SSL_CERT_DIR` para indicar ao OpenSSL
|
||||
onde procurar certificados CA:
|
||||
|
||||
```console
|
||||
# Define variáveis de ambiente para certificados TLS
|
||||
export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||
export SSL_CERT_DIR=/etc/ssl/certs
|
||||
```
|
||||
216
docs/pt-br/laravel.md
Normal file
216
docs/pt-br/laravel.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# Laravel
|
||||
|
||||
## Docker
|
||||
|
||||
Servir uma aplicação web [Laravel](https://laravel.com) com FrankenPHP é tão
|
||||
fácil quanto montar o projeto no diretório `/app` da imagem oficial do Docker.
|
||||
|
||||
Execute este comando a partir do diretório principal da sua aplicação Laravel:
|
||||
|
||||
```console
|
||||
docker run -p 80:80 -p 443:443 -p 443:443/udp -v $PWD:/app dunglas/frankenphp
|
||||
```
|
||||
|
||||
E divirta-se!
|
||||
|
||||
## Instalação local
|
||||
|
||||
Alternativamente, você pode executar seus projetos Laravel com FrankenPHP a
|
||||
partir da sua máquina local:
|
||||
|
||||
1. [Baixe o binário correspondente ao seu sistema](../../#getting-started).
|
||||
2. Adicione a seguinte configuração a um arquivo chamado `Caddyfile` no
|
||||
diretório raiz do seu projeto Laravel:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp
|
||||
}
|
||||
|
||||
# O nome de domínio do seu servidor
|
||||
localhost {
|
||||
# Define o diretório webroot/ como root public/
|
||||
root public/
|
||||
# Habilita a compressão (opcional)
|
||||
encode zstd br gzip
|
||||
# Executa os arquivos PHP a partir do diretório public/ e serve os assets
|
||||
php_server {
|
||||
try_files {path} index.php
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Inicie o FrankenPHP a partir do diretório raiz do seu projeto Laravel:
|
||||
`frankenphp run`.
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
O Octane pode ser instalado através do gerenciador de pacotes Composer:
|
||||
|
||||
```console
|
||||
composer require laravel/octane
|
||||
```
|
||||
|
||||
Após instalar o Octane, você pode executar o comando `octane:install` do
|
||||
Artisan, que instalará o arquivo de configuração do Octane em sua aplicação:
|
||||
|
||||
```console
|
||||
php artisan octane:install --server=frankenphp
|
||||
```
|
||||
|
||||
O servidor Octane pode ser iniciado por meio do comando `octane:frankenphp` do
|
||||
Artisan.
|
||||
|
||||
```console
|
||||
php artisan octane:frankenphp
|
||||
```
|
||||
|
||||
O comando `octane:frankenphp` pode receber as seguintes opções:
|
||||
|
||||
- `--host`: O endereço IP ao qual o servidor deve se vincular (padrão:
|
||||
`127.0.0.1`).
|
||||
- `--port`: A porta na qual o servidor deve estar disponível (padrão: `8000`).
|
||||
- `--admin-port`: A porta na qual o servidor de administração deve estar
|
||||
disponível (padrão: `2019`).
|
||||
- `--workers`: O número de workers que devem estar disponíveis para processar
|
||||
requisições (padrão: `auto`).
|
||||
- `--max-requests`: O número de requisições a serem processadas antes de
|
||||
recarregar o servidor (padrão: `500`).
|
||||
- `--caddyfile`: O caminho para o arquivo `Caddyfile` do FrankenPHP (padrão:
|
||||
[stub de `Caddyfile` no Laravel Octane](https://github.com/laravel/octane/blob/2.x/src/Commands/stubs/Caddyfile)).
|
||||
- `--https`: Habilita HTTPS, HTTP/2 e HTTP/3 e gera e renova certificados
|
||||
automaticamente.
|
||||
- `--http-redirect`: Habilita o redirecionamento de HTTP para HTTPS (somente
|
||||
- habilitado se `--https` for passada).
|
||||
- `--watch`: Recarrega o servidor automaticamente quando a aplicação é
|
||||
modificada.
|
||||
- `--poll`: Usa o polling do sistema de arquivos durante a verificação para
|
||||
monitorar arquivos em uma rede.
|
||||
- `--log-level`: Registra mensagens de log no nível de log especificado ou acima
|
||||
dele, usando o logger nativo do Caddy.
|
||||
|
||||
> [!TIP]
|
||||
> Para obter logs JSON estruturados (útil ao usar soluções de análise de logs),
|
||||
> passe explicitamente a opção `--log-level`.
|
||||
|
||||
Saiba mais sobre o
|
||||
[Laravel Octane em sua documentação oficial](https://laravel.com/docs/octane).
|
||||
|
||||
## Aplicações Laravel como binários independentes
|
||||
|
||||
Usando o [recurso de incorporação de aplicativos do FrankenPHP](embed.md), é
|
||||
possível distribuir aplicativos Laravel como binários independentes.
|
||||
|
||||
Siga estes passos para empacotar sua aplicação Laravel como um binário
|
||||
independente para Linux:
|
||||
|
||||
1. Crie um arquivo chamado `static-build.Dockerfile` no repositório da sua
|
||||
aplicação:
|
||||
|
||||
```dockerfile
|
||||
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder
|
||||
|
||||
# Copia sua aplicação
|
||||
WORKDIR /go/src/app/dist/app
|
||||
COPY . .
|
||||
|
||||
# Remove os testes e outros arquivos desnecessários para economizar espaço
|
||||
# Como alternativa, adicione esses arquivos a um arquivo .dockerignore
|
||||
RUN rm -Rf tests/
|
||||
|
||||
# Copia o arquivo .env
|
||||
RUN cp .env.example .env
|
||||
# Altera APP_ENV e APP_DEBUG para que estejam prontas para produção
|
||||
RUN sed -i'' -e 's/^APP_ENV=.*/APP_ENV=production/' -e 's/^APP_DEBUG=.*/APP_DEBUG=false/' .env
|
||||
|
||||
# Faça outras alterações no seu arquivo .env, se necessário
|
||||
|
||||
# Instala as dependências
|
||||
RUN composer install --ignore-platform-reqs --no-dev -a
|
||||
|
||||
# Compila o binário estático
|
||||
WORKDIR /go/src/app/
|
||||
RUN EMBED=dist/app/ ./build-static.sh
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Alguns arquivos `.dockerignore` ignorarão o diretório `vendor/` e os
|
||||
> arquivos `.env`.
|
||||
> Certifique-se de ajustar ou remover o arquivo `.dockerignore` antes da
|
||||
> compilação.
|
||||
|
||||
2. Construa:
|
||||
|
||||
```console
|
||||
docker build -t static-laravel-app -f static-build.Dockerfile .
|
||||
```
|
||||
|
||||
3. Extraia o binário:
|
||||
|
||||
```console
|
||||
docker cp $(docker create --name static-laravel-app-tmp static-laravel-app):/go/src/app/dist/frankenphp-linux-x86_64 frankenphp ; docker rm static-laravel-app-tmp
|
||||
```
|
||||
|
||||
4. Popule os caches:
|
||||
|
||||
```console
|
||||
frankenphp php-cli artisan optimize
|
||||
```
|
||||
|
||||
5. Execute as migrações de banco de dados (se houver):
|
||||
|
||||
```console
|
||||
frankenphp php-cli artisan migrate
|
||||
```
|
||||
|
||||
6. Gere a chave secreta da aplicação:
|
||||
|
||||
```console
|
||||
frankenphp php-cli artisan key:generate
|
||||
```
|
||||
|
||||
7. Inicie o servidor:
|
||||
|
||||
```console
|
||||
frankenphp php-server
|
||||
```
|
||||
|
||||
Agora sua aplicação está pronta!
|
||||
|
||||
Saiba mais sobre as opções disponíveis e como compilar binários para outros
|
||||
sistemas operacionais na documentação de
|
||||
[incorporação de aplicações](embed.md).
|
||||
|
||||
### Alterando o caminho do armazenamento
|
||||
|
||||
Por padrão, o Laravel armazena arquivos enviados, caches, logs, etc., no
|
||||
diretório `storage/` da aplicação.
|
||||
Isso não é adequado para aplicações embarcadas, pois cada nova versão será
|
||||
extraída para um diretório temporário diferente.
|
||||
|
||||
Defina a variável de ambiente `LARAVEL_STORAGE_PATH` (por exemplo, no seu
|
||||
arquivo `.env`) ou chame o método
|
||||
`Illuminate\Foundation\Application::useStoragePath()` para usar um diretório
|
||||
fora do diretório temporário.
|
||||
|
||||
### Executando o Octane com binários independentes
|
||||
|
||||
É possível até empacotar aplicações Octane do Laravel como binários
|
||||
independentes!
|
||||
|
||||
Para fazer isso, [instale o Octane corretamente](#laravel-octane) e siga os
|
||||
passos descritos na
|
||||
[seção anterior](#aplicações-laravel-como-binários-independentes).
|
||||
|
||||
Em seguida, para iniciar o FrankenPHP em modo worker através do Octane, execute:
|
||||
|
||||
```console
|
||||
PATH="$PWD:$PATH" frankenphp php-cli artisan octane:frankenphp
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Para que o comando funcione, o binário independente **deve** ser nomeado
|
||||
> `frankenphp` porque o Octane precisa de um programa chamado `frankenphp`
|
||||
> disponível no caminho.
|
||||
21
docs/pt-br/mercure.md
Normal file
21
docs/pt-br/mercure.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Tempo real
|
||||
|
||||
O FrankenPHP vem com um hub [Mercure](https://mercure.rocks) integrado!
|
||||
O Mercure permite que você envie eventos em tempo real para todos os
|
||||
dispositivos conectados: eles receberão um evento JavaScript instantaneamente.
|
||||
|
||||
Não é necessária nenhuma biblioteca JS ou SDK!
|
||||
|
||||

|
||||
|
||||
Para habilitar o hub Mercure, atualize o `Caddyfile` conforme descrito
|
||||
[no site do Mercure](https://mercure.rocks/docs/hub/config).
|
||||
|
||||
O caminho do hub Mercure é `/.well-known/mercure`.
|
||||
Ao executar o FrankenPHP dentro do Docker, a URL de envio completa seria
|
||||
`http://php/.well-known/mercure` (com `php` sendo o nome do contêiner que
|
||||
executa o FrankenPHP).
|
||||
|
||||
Para enviar atualizações do Mercure do seu código, recomendamos o
|
||||
[Componente Symfony Mercure](https://symfony.com/components/Mercure) (você não
|
||||
precisa do framework full-stack do Symfony para usá-lo).
|
||||
29
docs/pt-br/metrics.md
Normal file
29
docs/pt-br/metrics.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Métricas
|
||||
|
||||
Quando as [métricas do Caddy](https://caddyserver.com/docs/metrics) estão
|
||||
habilitadas, o FrankenPHP expõe as seguintes métricas:
|
||||
|
||||
- `frankenphp_total_threads`: O número total de threads PHP.
|
||||
- `frankenphp_busy_threads`: O número de threads PHP processando uma requisição
|
||||
no momento (workers em execução sempre consomem uma thread).
|
||||
- `frankenphp_queue_depth`: O número de requisições regulares na fila.
|
||||
- `frankenphp_total_workers{worker="[nome_do_worker]"}`: O número total de
|
||||
workers.
|
||||
- `frankenphp_busy_workers{worker="[nome_do_worker]"}`: O número de workers
|
||||
processando uma requisição no momento.
|
||||
- `frankenphp_worker_request_time{worker="[nome_do_worker]"}`: O tempo gasto no
|
||||
processamento de requisições por todos os workers.
|
||||
- `frankenphp_worker_request_count{worker="[nome_do_worker]"}`: O número de
|
||||
requisições processadas por todos os workers.
|
||||
- `frankenphp_ready_workers{worker="[nome_do_worker]"}`: O número de workers que
|
||||
chamaram `frankenphp_handle_request` pelo menos uma vez.
|
||||
- `frankenphp_worker_crashes{worker="[nome_do_worker]"}`: O número de vezes que
|
||||
um worker foi encerrado inesperadamente.
|
||||
- `frankenphp_worker_restarts{worker="[nome_do_worker]"}`: O número de vezes que
|
||||
um worker foi reiniciado deliberadamente.
|
||||
- `frankenphp_worker_queue_depth{worker="[nome_do_worker]"}`: O número de
|
||||
requisições na fila.
|
||||
|
||||
Para métricas de worker, o placeholder `[nome_do_worker]` é substituído pelo
|
||||
nome do worker no Caddyfile; caso contrário, o caminho absoluto do arquivo do
|
||||
worker será usado.
|
||||
214
docs/pt-br/performance.md
Normal file
214
docs/pt-br/performance.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Desempenho
|
||||
|
||||
Por padrão, o FrankenPHP tenta oferecer um bom equilíbrio entre desempenho e
|
||||
facilidade de uso.
|
||||
No entanto, é possível melhorar substancialmente o desempenho usando uma
|
||||
configuração apropriada.
|
||||
|
||||
## Número de threads e workers
|
||||
|
||||
Por padrão, o FrankenPHP inicia 2 vezes mais threads e workers (no modo worker)
|
||||
do que a quantidade de CPU disponível.
|
||||
|
||||
Os valores apropriados dependem muito de como sua aplicação foi escrita, do que
|
||||
ela faz e do seu hardware.
|
||||
Recomendamos fortemente alterar esses valores.
|
||||
Para melhor estabilidade do sistema, recomenda-se ter `num_threads` x
|
||||
`memory_limit` < `available_memory`.
|
||||
|
||||
Para encontrar os valores corretos, é melhor executar testes de carga simulando
|
||||
tráfego real.
|
||||
[k6](https://k6.io) e [Gatling](https://gatling.io) são boas ferramentas para
|
||||
isso.
|
||||
|
||||
Para configurar o número de threads, use a opção `num_threads` das diretivas
|
||||
`php_server` e `php`.
|
||||
Para alterar o número de workers, use a opção `num` da seção `worker` da
|
||||
diretiva `frankenphp`.
|
||||
|
||||
### `max_threads`
|
||||
|
||||
Embora seja sempre melhor saber exatamente como será o seu tráfego, aplicações
|
||||
reais tendem a ser mais imprevisíveis.
|
||||
A [configuração](config.md#configuracao-do-caddyfile) `max_threads` permite que
|
||||
o FrankenPHP gere threads adicionais automaticamente em tempo de execução até o
|
||||
limite especificado.
|
||||
`max_threads` pode ajudar você a descobrir quantas threads são necessárias para
|
||||
lidar com seu tráfego e pode tornar o servidor mais resiliente a picos de
|
||||
latência.
|
||||
Se definido como `auto`, o limite será estimado com base no `memory_limit` em
|
||||
seu `php.ini`.
|
||||
Caso contrário, `auto` assumirá como padrão o valor 2x `num_threads`.
|
||||
Lembre-se de que `auto` pode subestimar bastante o número de threads
|
||||
necessárias.
|
||||
`max_threads` é semelhante ao
|
||||
[pm.max_children](https://www.php.net/manual/pt_BR/install.fpm.configuration.php#pm.max-children)
|
||||
do PHP FPM.
|
||||
A principal diferença é que o FrankenPHP usa threads em vez de processos e os
|
||||
delega automaticamente entre diferentes worker scripts e o modo clássico,
|
||||
conforme necessário.
|
||||
|
||||
## Modo worker
|
||||
|
||||
Habilitar [o modo worker](worker.md) melhora drasticamente o desempenho, mas sua
|
||||
aplicação precisa ser adaptada para ser compatível com este modo: você precisa
|
||||
criar um worker script e garantir que a aplicação não esteja com vazamento de
|
||||
memória.
|
||||
|
||||
## Não use `musl`
|
||||
|
||||
A variante Alpine Linux das imagens oficiais do Docker e os binários padrão que
|
||||
fornecemos usam [a biblioteca C `musl`](https://musl.libc.org).
|
||||
|
||||
O PHP é conhecido por ser
|
||||
[mais lento](https://gitlab.alpinelinux.org/alpine/aports/-/issues/14381)
|
||||
ao usar esta biblioteca C alternativa em vez da biblioteca GNU tradicional,
|
||||
especialmente quando compilado no modo ZTS (thread-safe), necessário para o
|
||||
FrankenPHP.
|
||||
A diferença pode ser significativa em um ambiente com muitas threads.
|
||||
|
||||
Além disso,
|
||||
[alguns bugs só acontecem ao usar `musl`](https://github.com/php/php-src/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen+label%3ABug+musl).
|
||||
|
||||
Em ambientes de produção, recomendamos o uso do FrankenPHP vinculado à `glibc`.
|
||||
|
||||
Isso pode ser feito usando as imagens Docker do Debian (o padrão), baixando o
|
||||
binário com sufixo -gnu de nossos
|
||||
[Lançamentos](https://github.com/dunglas/frankenphp/releases) ou
|
||||
[compilando o FrankenPHP a partir dos fontes](compile.md).
|
||||
|
||||
Como alternativa, fornecemos binários `musl` estáticos compilados com
|
||||
[o alocador `mimalloc`](https://github.com/microsoft/mimalloc), o que alivia os
|
||||
problemas em cenários com threads.
|
||||
|
||||
## Configuração de Tempo de Execução do Go
|
||||
|
||||
O FrankenPHP é escrito em Go.
|
||||
|
||||
Em geral, o tempo de execução do Go não requer nenhuma configuração especial,
|
||||
mas em certas circunstâncias, configurações específicas melhoram o desempenho.
|
||||
|
||||
Você provavelmente deseja definir a variável de ambiente `GODEBUG` como
|
||||
`cgocheck=0` (o padrão nas imagens Docker do FrankenPHP).
|
||||
|
||||
Se você executa o FrankenPHP em contêineres (Docker, Kubernetes, LXC...) e
|
||||
limita a memória disponível para os contêineres, defina a variável de ambiente
|
||||
`GOMEMLIMIT` para a quantidade de memória disponível.
|
||||
|
||||
Para mais detalhes,
|
||||
[a página de documentação do Go dedicada a este assunto](https://pkg.go.dev/runtime#hdr-Environment_Variables)
|
||||
é uma leitura obrigatória para aproveitar ao máximo o tempo de execução.
|
||||
|
||||
## `file_server`
|
||||
|
||||
Por padrão, a diretiva `php_server` configura automaticamente um servidor de
|
||||
arquivos para servir arquivos estáticos (assets) armazenados no diretório raiz.
|
||||
|
||||
Este recurso é conveniente, mas tem um custo.
|
||||
Para desativá-lo, use a seguinte configuração:
|
||||
|
||||
```caddyfile
|
||||
php_server {
|
||||
file_server off
|
||||
}
|
||||
```
|
||||
|
||||
## `try_files`
|
||||
|
||||
Além de arquivos estáticos e arquivos PHP, `php_server` também tentará servir o
|
||||
arquivo index da sua aplicação e os arquivos index de diretório (`/path/` ->
|
||||
`/path/index.php`).
|
||||
Se você não precisa de arquivos index de diretório, pode desativá-los definindo
|
||||
explicitamente `try_files` assim:
|
||||
|
||||
```caddyfile
|
||||
php_server {
|
||||
try_files {path} index.php
|
||||
root /raiz/da/sua/aplicacao # adicionar explicitamente a raiz aqui permite um melhor armazenamento em cache
|
||||
}
|
||||
```
|
||||
|
||||
Isso pode reduzir significativamente o número de operações desnecessárias com
|
||||
arquivos.
|
||||
|
||||
Uma abordagem alternativa com 0 operações desnecessárias no sistema de arquivos
|
||||
seria usar a diretiva `php` e dividir os arquivos do PHP por caminho.
|
||||
Essa abordagem funciona bem se toda a sua aplicação for servida por um arquivo
|
||||
de entrada.
|
||||
Um exemplo de [configuração](config.md#configuracao-do-caddyfile) que serve
|
||||
arquivos estáticos a partir de uma pasta `/assets` poderia ser assim:
|
||||
|
||||
```caddyfile
|
||||
route {
|
||||
@assets {
|
||||
path /assets/*
|
||||
}
|
||||
|
||||
# tudo a partir de /assets é gerenciado pelo servidor de arquivos
|
||||
file_server @assets {
|
||||
root /raiz/da/sua/aplicacao
|
||||
}
|
||||
|
||||
# tudo o que não está em /assets é gerenciado pelo seu arquivo index ou worker PHP
|
||||
rewrite index.php
|
||||
php {
|
||||
root /raiz/da/sua/aplicacao # adicionar explicitamente a raiz aqui permite um melhor armazenamento em cache
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Placeholders
|
||||
|
||||
Você pode usar
|
||||
[placeholders](https://caddyserver.com/docs/conventions#placeholders) nas
|
||||
diretivas `root` e `env`.
|
||||
No entanto, isso impede o armazenamento em cache desses valores e acarreta um
|
||||
custo significativo de desempenho.
|
||||
|
||||
Se possível, evite placeholders nessas diretivas.
|
||||
|
||||
## `resolve_root_symlink`
|
||||
|
||||
Por padrão, se o diretório raiz for um link simbólico, ele será resolvido
|
||||
automaticamente pelo FrankenPHP (isso é necessário para o funcionamento correto
|
||||
do PHP).
|
||||
Se o diretório raiz não for um link simbólico, você pode desativar esse recurso.
|
||||
|
||||
```caddyfile
|
||||
php_server {
|
||||
resolve_root_symlink false
|
||||
}
|
||||
```
|
||||
|
||||
Isso melhorará o desempenho se a diretiva `root` contiver
|
||||
[placeholders](https://caddyserver.com/docs/conventions#placeholders).
|
||||
O ganho será insignificante em outros casos.
|
||||
|
||||
## Logs
|
||||
|
||||
O logging é obviamente muito útil, mas, por definição, requer operações de E/S e
|
||||
alocações de memória, o que reduz consideravelmente o desempenho.
|
||||
Certifique-se de
|
||||
[definir o nível de logging](https://caddyserver.com/docs/caddyfile/options#log)
|
||||
corretamente e registrar em log apenas o necessário.
|
||||
|
||||
## Desempenho do PHP
|
||||
|
||||
O FrankenPHP usa o interpretador PHP oficial.
|
||||
Todas as otimizações de desempenho usuais relacionadas ao PHP se aplicam ao
|
||||
FrankenPHP.
|
||||
|
||||
Em particular:
|
||||
|
||||
- verifique se o [OPcache](https://www.php.net/manual/pt_BR/book.opcache.php)
|
||||
está instalado, habilitado e configurado corretamente.
|
||||
- habilite as
|
||||
[otimizações do carregador automático do Composer](https://getcomposer.org/doc/articles/autoloader-optimization.md).
|
||||
- certifique-se de que o cache do `realpath` seja grande o suficiente para as
|
||||
necessidades da sua aplicação.
|
||||
- use
|
||||
[pré-carregamento](https://www.php.net/manual/pt_BR/opcache.preloading.php).
|
||||
|
||||
Para mais detalhes, leia
|
||||
[a entrada dedicada na documentação do Symfony](https://symfony.com/doc/current/performance.html)
|
||||
(a maioria das dicas é útil mesmo se você não usar o Symfony).
|
||||
170
docs/pt-br/production.md
Normal file
170
docs/pt-br/production.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Implantando em produção
|
||||
|
||||
Neste tutorial, aprenderemos como implantar uma aplicação PHP em um único
|
||||
servidor usando o Docker Compose.
|
||||
|
||||
Se você estiver usando o Symfony, prefira ler a entrada de documentação
|
||||
[Implantar em produção](https://github.com/dunglas/symfony-docker/blob/main/docs/production.md)
|
||||
do projeto Docker do Symfony (que usa FrankenPHP).
|
||||
|
||||
Se você estiver usando a API Platform (que também usa FrankenPHP), consulte
|
||||
[a documentação de implantação do framework](https://api-platform.com/docs/deployment/).
|
||||
|
||||
## Preparando sua aplicação
|
||||
|
||||
Primeiro, crie um `Dockerfile` no diretório raiz do seu projeto PHP:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# Certifique-se de substituir "seu-nome-de-dominio.example.com" pelo seu nome de
|
||||
# domínio
|
||||
ENV SERVER_NAME=seu-nome-de-dominio.example.com
|
||||
# Se quiser desabilitar o HTTPS, use este valor:
|
||||
#ENV SERVER_NAME=:80
|
||||
|
||||
# Habilita as configurações de produção do PHP
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Copia os arquivos PHP do seu projeto para o diretório public
|
||||
COPY . /app/public
|
||||
# Se você usa Symfony ou Laravel, precisa copiar o projeto inteiro:
|
||||
#COPY . /app
|
||||
```
|
||||
|
||||
Consulte [Criando uma imagem Docker personalizada](docker.md) para mais detalhes
|
||||
e opções, e para aprender como personalizar a configuração, instalar extensões
|
||||
PHP e módulos Caddy.
|
||||
|
||||
Se o seu projeto usa o Composer, certifique-se de incluí-lo na imagem Docker e
|
||||
instalar suas dependências.
|
||||
|
||||
Em seguida, adicione um arquivo `compose.yaml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
|
||||
# Volumes necessários para certificados e configuração do Caddy
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Os exemplos anteriores são destinados ao uso em produção.
|
||||
> Em desenvolvimento, você pode querer usar um volume, uma configuração PHP
|
||||
> diferente e um valor diferente para a variável de ambiente `SERVER_NAME`.
|
||||
>
|
||||
> Consulte o projeto [Symfony Docker](https://github.com/dunglas/symfony-docker)
|
||||
> (que usa FrankenPHP) para um exemplo mais avançado usando imagens
|
||||
> multiestágio, Composer, extensões PHP extras, etc.
|
||||
|
||||
Finalmente, se você usa Git, faça o commit e o push desses arquivos.
|
||||
|
||||
## Preparando um servidor
|
||||
|
||||
Para implantar sua aplicação em produção, você precisa de um servidor.
|
||||
Neste tutorial, usaremos uma máquina virtual fornecida pela DigitalOcean, mas
|
||||
qualquer servidor Linux pode funcionar.
|
||||
Se você já possui um servidor Linux com o Docker instalado, pode pular direto
|
||||
para [a próxima seção](#configurando-um-nome-de-domínio).
|
||||
|
||||
Caso contrário, use [este link de afiliado](https://m.do.co/c/5d8aabe3ab80) para
|
||||
obter US$ 200 em créditos gratuitos, crie uma conta e clique em "Create a
|
||||
Droplet".
|
||||
Em seguida, clique na aba "Marketplace" na seção "Choose an image" e procure a
|
||||
aplicação "Docker".
|
||||
Isso provisionará um servidor Ubuntu com as versões mais recentes do Docker e do
|
||||
Docker Compose já instaladas!
|
||||
|
||||
Para fins de teste, os planos mais baratos serão suficientes.
|
||||
Para uso real em produção, você provavelmente escolherá um plano na seção
|
||||
"General Purpose" que atenda às suas necessidades.
|
||||
|
||||

|
||||
|
||||
Você pode manter os padrões para outras configurações ou ajustá-los de acordo
|
||||
com suas necessidades.
|
||||
Não se esqueça de adicionar sua chave SSH ou criar uma senha e, em seguida,
|
||||
clicar no botão "Finalize and create".
|
||||
|
||||
Em seguida, aguarde alguns segundos enquanto seu Droplet é provisionado.
|
||||
Quando seu Droplet estiver pronto, use SSH para se conectar:
|
||||
|
||||
```console
|
||||
ssh root@<droplet-ip>
|
||||
```
|
||||
|
||||
## Configurando um nome de domínio
|
||||
|
||||
Na maioria dos casos, você precisará associar um nome de domínio ao seu site.
|
||||
Se você ainda não possui um nome de domínio, precisará comprar um por meio de um
|
||||
registrar.
|
||||
|
||||
Em seguida, crie um registro DNS do tipo `A` para o seu nome de domínio,
|
||||
apontando para o endereço IP do seu servidor:
|
||||
|
||||
```dns
|
||||
seu-nome-de-dominio.example.com. IN A <ip-do-seu-servidor>
|
||||
```
|
||||
|
||||
Exemplo com o serviço DigitalOcean Domains ("Networking" > "Domains"):
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> O Let's Encrypt, o serviço usado por padrão pelo FrankenPHP para gerar
|
||||
> automaticamente um certificado TLS, não suporta o uso de endereços IP.
|
||||
> O uso de um nome de domínio é obrigatório para usar o Let's Encrypt.
|
||||
|
||||
## Implantando
|
||||
|
||||
Copie seu projeto para o servidor usando `git clone`, `scp` ou qualquer outra
|
||||
ferramenta que atenda às suas necessidades.
|
||||
Se você usa o GitHub, pode ser útil usar
|
||||
[uma chave de implantação](https://docs.github.com/en/free-pro-team@latest/developers/overview/managing-deploy-keys#deploy-keys).
|
||||
Chaves de implantação também são [suportadas pelo GitLab](https://docs.gitlab.com/ee/user/project/deploy_keys/).
|
||||
|
||||
Exemplo com Git:
|
||||
|
||||
```console
|
||||
git clone git@github.com:<usuario>/<nome-do-projeto>.git
|
||||
```
|
||||
|
||||
Acesse o diretório que contém seu projeto (`<nome-do-projeto>`) e inicie a
|
||||
aplicação em modo de produção:
|
||||
|
||||
```console
|
||||
docker compose up --wait
|
||||
```
|
||||
|
||||
Seu servidor está funcionando e um certificado HTTPS foi gerado automaticamente
|
||||
para você.
|
||||
Acesse `https://seu-nome-de-dominio.example.com` e divirta-se!
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> O Docker pode ter uma camada de cache; certifique-se de ter a compilação
|
||||
> correta para cada implantação ou reconstrua seu projeto com a opção
|
||||
> `--no-cache` para evitar problemas de cache.
|
||||
|
||||
## Implantando em múltiplos nós
|
||||
|
||||
Se você deseja implantar sua aplicação em um cluster de máquinas, pode usar o
|
||||
[Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/), que é
|
||||
compatível com os arquivos Compose fornecidos.
|
||||
Para implantar no Kubernetes, consulte o
|
||||
[chart do Helm fornecido com a API Platform](https://api-platform.com/docs/deployment/kubernetes/),
|
||||
que usa FrankenPHP.
|
||||
208
docs/pt-br/static.md
Normal file
208
docs/pt-br/static.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# Criar uma compilação estática
|
||||
|
||||
Em vez de usar uma instalação local da biblioteca PHP, é possível criar uma
|
||||
compilação estática ou principalmente estática do FrankenPHP graças ao excelente
|
||||
[projeto static-php-cli](https://github.com/crazywhalecc/static-php-cli) (apesar
|
||||
do nome, este projeto suporta todas as SAPIs, não apenas CLI).
|
||||
|
||||
Com este método, um único binário portátil conterá o interpretador PHP, o
|
||||
servidor web Caddy e o FrankenPHP!
|
||||
|
||||
Executáveis nativos totalmente estáticos não requerem dependências e podem até
|
||||
ser executados na
|
||||
[imagem Docker `scratch`](https://docs.docker.com/build/building/base-images/#create-a-minimal-base-image-using-scratch).
|
||||
No entanto, eles não podem carregar extensões PHP dinâmicas (como o Xdebug) e
|
||||
têm algumas limitações por usarem a `libc` `musl`.
|
||||
|
||||
A maioria dos binários estáticos requer apenas `glibc` e pode carregar extensões
|
||||
dinâmicas.
|
||||
|
||||
Sempre que possível, recomendamos o uso de compilações principalmente estáticas
|
||||
baseadas na `glibc`.
|
||||
|
||||
O FrankenPHP também suporta
|
||||
[a incorporação da aplicação PHP no binário estático](embed.md).
|
||||
|
||||
## Linux
|
||||
|
||||
Fornecemos imagens Docker para compilar binários estáticos para Linux:
|
||||
|
||||
### Compilação totalmente estática baseada na `musl`
|
||||
|
||||
Para um binário totalmente estático que roda em qualquer distribuição Linux sem
|
||||
dependências, mas não suporta carregamento dinâmico de extensões:
|
||||
|
||||
```console
|
||||
docker buildx bake --load static-builder-musl
|
||||
docker cp $(docker create --name static-builder-musl dunglas/frankenphp:static-builder-musl):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp ; docker rm static-builder-musl
|
||||
```
|
||||
|
||||
Para melhor desempenho em cenários com alta concorrência, considere usar o
|
||||
alocador [`mimalloc`](https://github.com/microsoft/mimalloc).
|
||||
|
||||
```console
|
||||
docker buildx bake --load --set static-builder-musl.args.MIMALLOC=1 static-builder-musl
|
||||
```
|
||||
|
||||
### Compilação principalmente estática baseada na `glibc` (com suporte a extensões dinâmicas)
|
||||
|
||||
Para um binário que suporta o carregamento dinâmico de extensões PHP, mantendo
|
||||
as extensões selecionadas compiladas estaticamente:
|
||||
|
||||
```console
|
||||
docker buildx bake --load static-builder-gnu
|
||||
docker cp $(docker create --name static-builder-gnu dunglas/frankenphp:static-builder-gnu):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp ; docker rm static-builder-gnu
|
||||
```
|
||||
|
||||
Este binário suporta todas as versões 2.17 e superiores da `glibc`, mas não roda
|
||||
em sistemas baseados em `musl` (como o Alpine Linux).
|
||||
|
||||
O binário principalmente estático (exceto a `glibc`) resultante é chamado
|
||||
`frankenphp` e está disponível no diretório atual.
|
||||
|
||||
Se você quiser compilar o binário estático sem o Docker, consulte as instruções
|
||||
para macOS, que também funcionam para Linux.
|
||||
|
||||
### Extensões personalizadas
|
||||
|
||||
Por padrão, as extensões PHP mais populares são compiladas.
|
||||
|
||||
Para reduzir o tamanho do binário e a superfície de ataque, você pode escolher a
|
||||
lista de extensões a serem compiladas usando o `ARG` `PHP_EXTENSIONS` do Docker.
|
||||
|
||||
Por exemplo, execute o seguinte comando para compilar apenas a extensão
|
||||
`opcache`:
|
||||
|
||||
```console
|
||||
docker buildx bake --load --set static-builder-musl.args.PHP_EXTENSIONS=opcache,pdo_sqlite static-builder-musl
|
||||
# ...
|
||||
```
|
||||
|
||||
Para adicionar bibliotecas que habilitem funcionalidades adicionais às extensões
|
||||
habilitadas, você pode passar o `ARG` `PHP_EXTENSION_LIBS` do Docker:
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder-musl.args.PHP_EXTENSIONS=gd \
|
||||
--set static-builder-musl.args.PHP_EXTENSION_LIBS=libjpeg,libwebp \
|
||||
static-builder-musl
|
||||
```
|
||||
|
||||
### Módulos Caddy extras
|
||||
|
||||
Para adicionar módulos Caddy extras ou passar outros argumentos para o
|
||||
[`xcaddy`](https://github.com/caddyserver/xcaddy), use o `ARG` `XCADDY_ARGS` do
|
||||
Docker:
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder-musl.args.XCADDY_ARGS="--with github.com/darkweak/souin/plugins/caddy --with github.com/dunglas/caddy-cbrotli --with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy" \
|
||||
static-builder-musl
|
||||
```
|
||||
|
||||
Neste exemplo, adicionamos o módulo de cache HTTP [Souin](https://souin.io) para
|
||||
o Caddy, bem como os módulos
|
||||
[cbrotli](https://github.com/dunglas/caddy-cbrotli),
|
||||
[Mercure](https://mercure.rocks) e [Vulcain](https://vulcain.rocks).
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Os módulos cbrotli, Mercure e Vulcain são incluídos por padrão se
|
||||
> `XCADDY_ARGS` estiver vazio ou não definido.
|
||||
> Se você personalizar o valor de `XCADDY_ARGS`, deverá incluí-los
|
||||
> explicitamente se desejar que sejam incluídos.
|
||||
|
||||
Veja também como [personalizar a compilação](#personalizando-a-compilação).
|
||||
|
||||
### Token do GitHub
|
||||
|
||||
Se você atingir o limite de taxa da API do GitHub, defina um Token de Acesso
|
||||
Pessoal do GitHub em uma variável de ambiente chamada `GITHUB_TOKEN`:
|
||||
|
||||
```console
|
||||
GITHUB_TOKEN="xxx" docker --load buildx bake static-builder-musl
|
||||
# ...
|
||||
```
|
||||
|
||||
## macOS
|
||||
|
||||
Execute o seguinte script para criar um binário estático para macOS (você
|
||||
precisa ter o [Homebrew](https://brew.sh/) instalado):
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
Observação: este script também funciona no Linux (e provavelmente em outros
|
||||
sistemas Unix) e é usado internamente pelas imagens Docker que fornecemos.
|
||||
|
||||
## Personalizando a compilação
|
||||
|
||||
As seguintes variáveis de ambiente podem ser passadas para `docker build` e para
|
||||
o script `build-static.sh` para personalizar a compilação estática:
|
||||
|
||||
- `FRANKENPHP_VERSION`: a versão do FrankenPHP a ser usada.
|
||||
- `PHP_VERSION`: a versão do PHP a ser usada.
|
||||
- `PHP_EXTENSIONS`: as extensões PHP a serem compiladas
|
||||
([lista de extensões suportadas](https://static-php.dev/en/guide/extensions.html)).
|
||||
- `PHP_EXTENSION_LIBS`: bibliotecas extras a serem compiladas que adicionam
|
||||
recursos às extensões.
|
||||
- `XCADDY_ARGS`: argumentos a passar para o
|
||||
[`xcaddy`](https://github.com/caddyserver/xcaddy), por exemplo, para adicionar
|
||||
módulos Caddy extras.
|
||||
- `EMBED`: caminho da aplicação PHP a ser incorporada no binário.
|
||||
- `CLEAN`: quando definida, a `libphp` e todas as suas dependências são
|
||||
compiladas do zero (sem cache).
|
||||
- `NO_COMPRESS`: não compacta o binário resultante usando UPX.
|
||||
- `DEBUG_SYMBOLS`: quando definida, os símbolos de depuração não serão removidos
|
||||
e serão adicionados ao binário.
|
||||
- `MIMALLOC`: (experimental, somente Linux) substitui `mallocng` da `musl` por
|
||||
[`mimalloc`](https://github.com/microsoft/mimalloc) para melhor desempenho.
|
||||
Recomendamos usar isso apenas para compilações direcionadas à `musl`; para
|
||||
`glibc`, prefira desabilitar essa opção e usar
|
||||
[`LD_PRELOAD`](https://microsoft.github.io/mimalloc/overrides.html) ao
|
||||
executar seu binário.
|
||||
- `RELEASE`: (somente pessoas mantenedoras) quando definida, o binário
|
||||
resultante será enviado para o GitHub.
|
||||
|
||||
## Extensões
|
||||
|
||||
Com os binários `glibc` ou baseados em macOS, você pode carregar extensões PHP
|
||||
dinamicamente.
|
||||
No entanto, essas extensões precisarão ser compiladas com suporte a ZTS.
|
||||
Como a maioria dos gerenciadores de pacotes não oferece atualmente versões ZTS
|
||||
de suas extensões, você terá que compilá-las você mesmo.
|
||||
|
||||
Para isso, você pode compilar e executar o contêiner Docker
|
||||
`static-builder-gnu`, acessá-lo remotamente e compilar as extensões com
|
||||
`./configure --with-php-config=/go/src/app/dist/static-php-cli/buildroot/bin/php-config`.
|
||||
|
||||
Passos de exemplo para [a extensão Xdebug](https://xdebug.org):
|
||||
|
||||
```console
|
||||
docker build -t gnu-ext -f static-builder-gnu.Dockerfile --build-arg FRANKENPHP_VERSION=1.0 .
|
||||
docker create --name static-builder-gnu -it gnu-ext /bin/sh
|
||||
docker start static-builder-gnu
|
||||
docker exec -it static-builder-gnu /bin/sh
|
||||
cd /go/src/app/dist/static-php-cli/buildroot/bin
|
||||
git clone https://github.com/xdebug/xdebug.git && cd xdebug
|
||||
source scl_source enable devtoolset-10
|
||||
../phpize
|
||||
./configure --with-php-config=/go/src/app/dist/static-php-cli/buildroot/bin/php-config
|
||||
make
|
||||
exit
|
||||
docker cp static-builder-gnu:/go/src/app/dist/static-php-cli/buildroot/bin/xdebug/modules/xdebug.so xdebug-zts.so
|
||||
docker cp static-builder-gnu:/go/src/app/dist/frankenphp-linux-$(uname -m) ./frankenphp
|
||||
docker stop static-builder-gnu
|
||||
docker rm static-builder-gnu
|
||||
docker rmi gnu-ext
|
||||
```
|
||||
|
||||
Isso criará `frankenphp` e `xdebug-zts.so` no diretório atual.
|
||||
Se você mover `xdebug-zts.so` para o diretório de extensões, adicione
|
||||
`zend_extension=xdebug-zts.so` ao seu `php.ini` e execute o FrankenPHP, ele
|
||||
carregará o Xdebug.
|
||||
203
docs/pt-br/worker.md
Normal file
203
docs/pt-br/worker.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Usando workers do FrankenPHP
|
||||
|
||||
Inicialize sua aplicação uma vez e mantenha-a na memória.
|
||||
O FrankenPHP processará as requisições recebidas em poucos milissegundos.
|
||||
|
||||
## Iniciando worker scripts
|
||||
|
||||
### Docker
|
||||
|
||||
Defina o valor da variável de ambiente `FRANKENPHP_CONFIG` como
|
||||
`worker /caminho/para/seu/script/worker.php`:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker /app/caminho/para/seu/script/worker.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### Binário independente
|
||||
|
||||
Use a opção `--worker` do comando `php-server` para servir o conteúdo do
|
||||
diretório atual usando um worker:
|
||||
|
||||
```console
|
||||
frankenphp php-server --worker /caminho/para/seu/script/worker.php
|
||||
```
|
||||
|
||||
Se a sua aplicação PHP estiver [embutida no binário](embed.md), você pode
|
||||
adicionar um `Caddyfile` personalizado no diretório raiz da aplicação.
|
||||
Ele será usado automaticamente.
|
||||
|
||||
Também é possível
|
||||
[reiniciar o worker em caso de alterações no arquivo](config.md#monitorando-alteracoes-em-arquivos)
|
||||
com a opção `--watch`.
|
||||
O comando a seguir acionará uma reinicialização se qualquer arquivo terminado em
|
||||
`.php` no diretório `/caminho/para/sua/aplicacao/` ou subdiretórios for
|
||||
modificado:
|
||||
|
||||
```console
|
||||
frankenphp php-server --worker /caminho/para/seu/script/worker.php --watch="/caminho/para/sua/aplicacao/**/*.php"
|
||||
```
|
||||
|
||||
## Tempo de execução do Symfony
|
||||
|
||||
O modo worker do FrankenPHP é suportado pelo
|
||||
[Componente Symfony Runtime](https://symfony.com/doc/current/components/runtime.html).
|
||||
Para iniciar qualquer aplicação Symfony em um worker, instale o pacote
|
||||
FrankenPHP do
|
||||
[tempo de execução do PHP](https://github.com/php-runtime/runtime):
|
||||
|
||||
```console
|
||||
composer require runtime/frankenphp-symfony
|
||||
```
|
||||
|
||||
Inicie seu servidor de aplicações definindo a variável de ambiente `APP_RUNTIME`
|
||||
para usar o tempo de execução Symfony do FrankenPHP:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
Consulte [a documentação dedicada](laravel.md#laravel-octane).
|
||||
|
||||
## Aplicações personalizadas
|
||||
|
||||
O exemplo a seguir mostra como criar seu próprio worker script sem depender de
|
||||
uma biblioteca de terceiros:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// public/index.php
|
||||
|
||||
// Impede o encerramento do worker script quando uma conexão do cliente for
|
||||
// interrompida
|
||||
ignore_user_abort(true);
|
||||
|
||||
// Inicializa sua aplicação
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$myApp = new \App\Kernel();
|
||||
$myApp->boot();
|
||||
|
||||
// Manipulador fora do loop para melhor desempenho (fazendo menos trabalho)
|
||||
$handler = static function () use ($myApp) {
|
||||
// Chamado quando uma requisição é recebida,
|
||||
// superglobals, php://input e similares são redefinidos
|
||||
echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
|
||||
};
|
||||
|
||||
$maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0);
|
||||
for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) {
|
||||
$keepRunning = \frankenphp_handle_request($handler);
|
||||
|
||||
// Faz algo depois de enviar a resposta HTTP
|
||||
$myApp->terminate();
|
||||
|
||||
// Chama o coletor de lixo para reduzir as chances de ele ser acionado no
|
||||
// meio da geração de uma página
|
||||
gc_collect_cycles();
|
||||
|
||||
if (!$keepRunning) break;
|
||||
}
|
||||
|
||||
// Limpeza
|
||||
$myApp->shutdown();
|
||||
```
|
||||
|
||||
Em seguida, inicie sua aplicação e use a variável de ambiente
|
||||
`FRANKENPHP_CONFIG` para configurar seu worker:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Por padrão, 2 workers por CPU são iniciados.
|
||||
Você também pode configurar o número de workers a serem iniciados:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php 42" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### Reiniciar o worker após um certo número de requisições
|
||||
|
||||
Como o PHP não foi originalmente projetado para processos de longa duração,
|
||||
ainda existem muitas bibliotecas e códigos legados que vazam memória.
|
||||
Uma solução alternativa para usar esse tipo de código no modo worker é reiniciar
|
||||
o worker script após processar um certo número de requisições:
|
||||
|
||||
O trecho de código de worker anterior permite configurar um número máximo de
|
||||
requisições a serem processadas, definindo uma variável de ambiente chamada
|
||||
`MAX_REQUESTS`.
|
||||
|
||||
### Reiniciar os workers manualmente
|
||||
|
||||
Embora seja possível reiniciar os workers
|
||||
[em alterações de arquivo](config.md#monitorando-alteracoes-em-arquivos), também
|
||||
é possível reiniciar todos os workers normalmente por meio da
|
||||
[API de administração do Caddy](https://caddyserver.com/docs/api).
|
||||
Se o administrador estiver habilitado no seu
|
||||
[Caddyfile](config.md#configuracao-do-caddyfile), você pode executar ping no
|
||||
endpoint de reinicialização com uma simples requisição POST como esta:
|
||||
|
||||
```console
|
||||
curl -X POST http://localhost:2019/frankenphp/workers/restart
|
||||
```
|
||||
|
||||
### Falhas de worker
|
||||
|
||||
Se um worker script travar com um código de saída diferente de zero, o
|
||||
FrankenPHP o reiniciará com uma estratégia de backoff exponencial.
|
||||
Se o worker script permanecer ativo por mais tempo do que o último backoff \* 2,
|
||||
ele não penalizará o worker script e o reiniciará novamente.
|
||||
No entanto, se o worker script continuar a falhar com um código de saída
|
||||
diferente de zero em um curto período de tempo (por exemplo, com um erro de
|
||||
digitação em um script), o FrankenPHP travará com o erro:
|
||||
`too many consecutive failures` (muitas falhas consecutivas).
|
||||
|
||||
## Comportamento das superglobais
|
||||
|
||||
As
|
||||
[superglobais do PHP](https://www.php.net/manual/pt_BR/language.variables.superglobals.php)
|
||||
(`$_SERVER`, `$_ENV`, `$_GET`...) se comportam da seguinte maneira:
|
||||
|
||||
- antes da primeira chamada para `frankenphp_handle_request()`, as superglobais
|
||||
contêm valores vinculados ao próprio worker script.
|
||||
- durante e após a chamada para `frankenphp_handle_request()`, as superglobais
|
||||
contêm valores gerados a partir da requisição HTTP processada.
|
||||
Cada chamada para `frankenphp_handle_request()` altera os valores das
|
||||
superglobais.
|
||||
|
||||
Para acessar as superglobais do worker script dentro do retorno de chamada, você
|
||||
deve copiá-las e importar a cópia para o escopo do retorno de chamada:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Copia a superglobal $_SERVER do worker antes da primeira chamada para
|
||||
// frankenphp_handle_request()
|
||||
$workerServer = $_SERVER;
|
||||
|
||||
$handler = static function () use ($workerServer) {
|
||||
var_dump($_SERVER); // $_SERVER vinculada à requisição
|
||||
var_dump($workerServer); // $_SERVER do worker script
|
||||
};
|
||||
|
||||
// ...
|
||||
```
|
||||
80
docs/pt-br/x-sendfile.md
Normal file
80
docs/pt-br/x-sendfile.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Servindo arquivos estáticos grandes com eficiência (`X-Sendfile`/`X-Accel-Redirect`)
|
||||
|
||||
Normalmente, arquivos estáticos podem ser servidos diretamente pelo servidor
|
||||
web, mas às vezes é necessário executar algum código PHP antes de enviá-los:
|
||||
controle de acesso, estatísticas, cabeçalhos HTTP personalizados...
|
||||
|
||||
Infelizmente, usar PHP para servir arquivos estáticos grandes é ineficiente em
|
||||
comparação com o uso direto do servidor web (sobrecarga de memória, desempenho
|
||||
reduzido...).
|
||||
|
||||
O FrankenPHP permite delegar o envio de arquivos estáticos ao servidor web
|
||||
**após** a execução de código PHP personalizado.
|
||||
|
||||
Para fazer isso, sua aplicação PHP precisa simplesmente definir um cabeçalho
|
||||
HTTP personalizado contendo o caminho do arquivo a ser servido.
|
||||
O FrankenPHP cuida do resto.
|
||||
|
||||
Esse recurso é conhecido como **`X-Sendfile`** para Apache e
|
||||
**`X-Accel-Redirect`** para NGINX.
|
||||
|
||||
Nos exemplos a seguir, assumimos que o diretório raiz do projeto é o diretório
|
||||
`public/` e que queremos usar PHP para servir arquivos armazenados fora do
|
||||
diretório `public/`, de um diretório chamado `arquivos-privados/`.
|
||||
|
||||
## Configuração
|
||||
|
||||
Primeiro, adicione a seguinte configuração ao seu `Caddyfile` para habilitar
|
||||
este recurso:
|
||||
|
||||
```patch
|
||||
root public/
|
||||
# ...
|
||||
|
||||
+ # Necessário para Symfony, Laravel e outros projetos que usam o componente
|
||||
+ # Symfony HttpFoundation
|
||||
+ request_header X-Sendfile-Type x-accel-redirect
|
||||
+ request_header X-Accel-Mapping ../arquivos-privados=/arquivos-privados
|
||||
+
|
||||
+ intercept {
|
||||
+ @accel header X-Accel-Redirect *
|
||||
+ handle_response @accel {
|
||||
+ root arquivos-privados/
|
||||
+ rewrite * {resp.header.X-Accel-Redirect}
|
||||
+ method * GET
|
||||
+
|
||||
+ # Remove o cabeçalho X-Accel-Redirect definido pelo PHP para maior
|
||||
+ # segurança
|
||||
+ header -X-Accel-Redirect
|
||||
+
|
||||
+ file_server
|
||||
+ }
|
||||
+ }
|
||||
|
||||
php_server
|
||||
```
|
||||
|
||||
## PHP simples
|
||||
|
||||
Defina o caminho relativo do arquivo (de `arquivos-privados/`) como o valor do
|
||||
cabeçalho `X-Accel-Redirect`:
|
||||
|
||||
```php
|
||||
header('X-Accel-Redirect: arquivo.txt');
|
||||
```
|
||||
|
||||
## Projetos que utilizam o componente Symfony HttpFoundation (Symfony, Laravel, Drupal...)
|
||||
|
||||
Symfony HttpFoundation
|
||||
[suporta nativamente este recurso](https://symfony.com/doc/current/components/http_foundation.html#serving-files).
|
||||
Ele determinará automaticamente o valor correto para o cabeçalho
|
||||
`X-Accel-Redirect` e o adicionará à resposta.
|
||||
|
||||
```php
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
BinaryFileResponse::trustXSendfileTypeHeader();
|
||||
$response = new BinaryFileResponse(__DIR__.'/../arquivos-privados/arquivo.txt');
|
||||
|
||||
// ...
|
||||
```
|
||||
Reference in New Issue
Block a user