dunglas / frankenphp

🧟 The modern PHP app server
https://frankenphp.dev
MIT License
6.96k stars 244 forks source link

Crash when running Laravel Octane #1039

Open jduan00 opened 2 months ago

jduan00 commented 2 months ago

What happened?

Description: We are experiencing crashes when running our Laravel application using the binary release of FrankenPHP (musl). However, when using the official FrankenPHP Docker image with the same Laravel application, everything works as expected.

Environment: • FrankenPHP Version: v1.2.5 • PHP Version: 8.3.11 • Caddy Version: v2.8.4 (h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=) • OS: Linux x64 (Ubuntu 24.x)

Issue Details: • Working scenario: Running the Laravel application inside the official FrankenPHP Docker image works without any issues. • Problematic scenario: When running the same Laravel application using the standalone binary release (musl), the application crashes frequently.

Request: We use a Docker deployment process based on Ubuntu 24.x, and while we are capable of recompiling FrankenPHP per the documentation, it would be highly beneficial to have an official binary distribution for glibc-based systems. This would simplify our deployment process and likely resolve the crashes related to musl incompatibility.

Thank you for your consideration!

Build Type

Official static build

Worker Mode

Yes

Operating System

GNU/Linux

CPU Architecture

x86_64

PHP configuration

PHP Version: 8.3.11

Relevant log output

No response

dunglas commented 2 months ago

You're very likely encountering https://github.com/php/php-src/issues/13648. The PHP Foundation is working on it: https://github.com/php/php-src/issues/14734

it would be highly beneficial to have an official binary distribution for glibc-based systems

It's unfortunately not that simple because unlike with musl, it's not really possible to create portable binaries with glibc. We'll have to add package for every distribution.

For Debian/Ubuntu, see https://github.com/dunglas/frankenphp/issues/1039

jduan00 commented 2 months ago

Thank you @dunglas for your prompt response. I understand your reasons for not making a portable binary with glibc. As I am playing around with your official docker image, it is working.

The size of the docker image is over 500MB, is it possible to slim it down? Thanks

jduan00 commented 2 months ago

Just a comparison:

REPOSITORY                   TAG       IMAGE ID       CREATED         SIZE
eaglwine/debian-frankenphp   latest    38d2a10971b5   2 minutes ago   665MB
dunglas/frankenphp           latest    15f7ddf8f380   22 hours ago    579MB
eaglwine/ubuntu-php83        latest    c83793361d63   5 weeks ago     261MB

1 based on dunglas/frankenphp, with added php extensions and supervisor, etc.

3 ubuntu minimal + php74 (php-fpm)

sukrokucing commented 2 months ago

Hi @dunglas, I am very flattered by your work. Since I am still a newbie here, a simple question:

Can I still start https://localhost:8000 with docker under wsl (windows)?

I am using laravel octane (from fresh install eg. composer create project, bla, bla--), and want to use frankenphp on my local machine

Trying image dunglas/frankenphp:latest-php8.3.7-bookworm, dunglas/frankenphp:latest-php8.3.7-alpine

but no luck 😔 (ERR_SSL_PROTOCOL_ERROR)

Anyway, great thanks!

jduan00 commented 2 months ago

@dunglas : I am happy to share that by doing multi-stage build, docker image size came down by almost an half!

REPOSITORY                     TAG             IMAGE ID       CREATED          SIZE
eaglwine/debian-frankenphp83   latest          47011976bff8   34 seconds ago   375MB

Dockerfile

FROM dunglas/frankenphp as builder

# Install php extensions
RUN install-php-extensions pdo_mysql gd intl zip opcache exif pcntl

# Start from a simple base
FROM debian:bookworm-slim AS base

COPY --from=builder /usr/local /usr/local
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer

RUN apt-get update && \
    apt-get install -yqq --no-install-recommends supervisor procps curl \
    libreadline8 libbrotli1 libxml2 libssl3 libsqlite3-0 libcurl4 libonig5 \
    libargon2-1 libpng16-16 libavif15 libwebp7 libxpm4 libfreetype6 libsodium23 libzip4 \
    unzip httping htop file p7zip-full \
    net-tools iputils-ping bind9-dnsutils jq vim-tiny

....
withinboredom commented 2 months ago

@jduan00, most likely those 'lost megabytes' are libraries used by extensions, like libmysql, libzip, libexif, etc, and your application will crash when trying to use some of those extensions.

As mentioned, the glibc build isn't "portable" and you can't just copy it over to another system.

@sukrokucing, your message is a bit off-topic and probably belongs in the discussion section instead. There isn't enough information to help with your specific problem, but SERVER_NAME="https://localhost:8000" ./frankenphp -c default/Caddyfile works for me. If you need help, please drop into the discussions tab at the top of the page and start a discussion!

jduan00 commented 2 months ago

@withinboredom : Actually we are on the same page, in the Dockerfile I am installing all required libraries. The docker image is still 378MB. We are doing a lot of QA Testing for a length of time before deciding to switch this to Production.

RUN apt-get update && \
    apt-get install -yqq --no-install-recommends supervisor procps curl \
    libreadline8 libbrotli1 libxml2 libssl3 libsqlite3-0 libcurl4 libonig5 \
    libargon2-1 libpng16-16 libavif15 libwebp7 libxpm4 libfreetype6 libsodium23 libzip4 \
    unzip httping htop file p7zip-full \
    net-tools iputils-ping bind9-dnsutils jq vim-tiny
withinboredom commented 2 months ago

If you don't mind, I'd be very interested and grateful to see a gist of the additional files in the frankenphp image. I wonder if it is stuff that got left behind from a build process (maybe even the base php image) or whatever.

https://github.com/GoogleContainerTools/container-diff isn't maintained anymore, but still works last I tried it.

jduan00 commented 2 months ago

@withinboredom : be happy to in a day. Just to confirm: container-diff on: dunglas/frankenphp vs eaglwine/debian-frankenphp83?

withinboredom commented 2 months ago

@jduan00 no rush, but that sounds right assuming eaglwine/debian-frankenphp83 is the image you are copying everything to manually.

sukrokucing commented 2 months ago

@withinboredom like this? #1041

@jduan00, most likely those 'lost megabytes' are libraries used by extensions, like libmysql, libzip, libexif, etc, and your application will crash when trying to use some of those extensions.

As mentioned, the glibc build isn't "portable" and you can't just copy it over to another system.

@sukrokucing, your message is a bit off-topic and probably belongs in the discussion section instead. There isn't enough information to help with your specific problem, but SERVER_NAME="https://localhost:8000" ./frankenphp -c default/Caddyfile works for me. If you need help, please drop into the discussions tab at the top of the page and start a discussion!

jduan00 commented 2 months ago

If you don't mind, I'd be very interested and grateful to see a gist of the additional files in the frankenphp image. I wonder if it is stuff that got left behind from a build process (maybe even the base php image) or whatever.

https://github.com/GoogleContainerTools/container-diff isn't maintained anymore, but still works last I tried it.

@withinboredom : can you please let me know the exact container-diff command options you like to see?

Here is what I have

Linux 5.15.0-1063-ibm #66-Ubuntu SMP Fri Aug 30 13:43:36 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
Ubuntu 22.04.5 LTS

REPOSITORY                     TAG       IMAGE ID       CREATED          SIZE
eaglwine/debian-frankenphp83   latest    5806d46e80e4   36 minutes ago   319MB
dunglas/frankenphp             latest    6b969579b9bc   15 hours ago     586MB

$ container-diff diff daemon://eaglwine/debian-frankenphp83:latest daemon://dunglas/frankenphp:latest
-----Size-----

Image size difference between eaglwine/debian-frankenphp83:latest and dunglas/frankenphp:latest:
SIZE1         SIZE2
306.6M        558.4M

$ container-diff diff daemon://eaglwine/debian-frankenphp83:latest daemon://dunglas/frankenphp:latest --type=history

-----History-----
// lots of info
jduan00 commented 2 months ago

@withinboredom FYI, here is the most important part of my Dockerfile. So far our Lavavel Octane app is passing QA test. More work to be done.

FROM dunglas/frankenphp as builder

USER root

# Install php extensions
RUN install-php-extensions pdo_mysql gd intl zip opcache exif pcntl
RUN rm -rf /usr/local/bin/phpdbg /usr/local/bin/php-cgi

# Start from a simple base
FROM debian:bookworm-slim AS base

COPY --from=builder /usr/local/bin /usr/local/bin
COPY --from=builder /usr/local/etc /usr/local/etc
COPY --from=builder /usr/local/lib /usr/local/lib
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer

# Install packages
RUN apt-get update && \
    apt-get install -yqq --no-install-recommends supervisor procps curl \
    libreadline8 libbrotli1 libxml2 libssl3 libsqlite3-0 libcurl4 libonig5 \
    libargon2-1 libpng16-16 libavif15 libwebp7 libxpm4 libfreetype6 libsodium23 libzip4 \
    unzip httping htop file p7zip-full \
    net-tools iputils-ping bind9-dnsutils jq vim-tiny && \
    apt-get install --reinstall ca-certificates && \
    apt autoremove -qy && \
    apt clean && \
    apt autoclean && \
    rm -rf /var/lib/apt/lists/*

# Drop in GEI files
WORKDIR /app
COPY --chown=root:root ./app /app
withinboredom commented 1 month ago

I suspect it is the /usr/local/src (IIRC) directory used to install extensions and contains the source code of php? For example, I suspect pecl won't be able to compile new extensions in your resulting docker image.

jduan00 commented 1 month ago

@withinboredom : the resulting docker image is minimized for deploying production apps, so no need to install or compile any additional PHP extensions. Thanks for looking into it!

calvinalkan commented 6 days ago

It also contains stuff like the gcc compiler, which should not be needed to deploy to prod?

What I do is build a static binary in docker with Multistage builds and then copy it to a slim base Image (could probably even use from scratch, but need to create a couple directories and users)

That way, it's like 24MB...