GithubHelp home page GithubHelp logo

exaco / laravel-octane-dockerfile Goto Github PK

View Code? Open in Web Editor NEW
476.0 13.0 73.0 189 KB

Production-ready Dockerfile for Laravel Octane (FrankenPHP, Swoole, RoadRunner) powered web services and microservices. Done right.

License: MIT License

Shell 10.77% Dockerfile 89.23%
laravel swoole octane dockerfile microservice docker horizon frankenphp roadrunner

laravel-octane-dockerfile's Introduction

Laravel Octane Dockerfile

License GitHub release (latest by date) GitHub closed pull requests GitHub Workflow Status GitHub Workflow Status GitHub Workflow Status

Production-ready Dockerfiles for Laravel Octane powered web services and microservices.

The Docker configuration provides the following setup:

  • PHP 8.2 and 8.3 official Debian-based images
  • Preconfigured JIT compiler and OPcache

Container modes

You can run the Docker container in different modes:

Mode CONTAINER_MODE HTTP server
HTTP Server (default) http FrankenPHP / Swoole / RoadRunner
Horizon horizon -
Scheduler scheduler -
Worker worker -

Usage

Building Docker image

  1. Clone this repository:
git clone --depth 1 [email protected]:exaco/laravel-octane-dockerfile.git
  1. Copy cloned directory content including deployment directory, Dockerfile, and .dockerignore into your Octane powered Laravel project
  2. Change the directory to your Laravel project
  3. Build your image:
docker build -t <image-name>:<tag> -f <your-octane-driver>.Dockerfile .

Running Docker container

# HTTP mode
docker run -p <port>:80 --rm <image-name>:<tag>

# Horizon mode
docker run -e CONTAINER_MODE=horizon --rm <image-name>:<tag>

# Scheduler mode
docker run -e CONTAINER_MODE=scheduler --rm <image-name>:<tag>

# HTTP mode with Horizon
docker run -e WITH_HORIZON=true -p <port>:80 --rm <image-name>:<tag>

# HTTP mode with Scheduler
docker run -e WITH_SCHEDULER=true -p <port>:80 --rm <image-name>:<tag>

# HTTP mode with Scheduler and Horizon
docker run -e WITH_SCHEDULER=true -e WITH_HORIZON=true -p <port>:80 --rm <image-name>:<tag>

# Worker mode
docker run -e CONTAINER_MODE=worker -e WORKER_COMMAND="php /var/www/html/artisan foo:bar" --rm <image-name>:<tag>

# Running a single command
docker run --rm <image-name>:<tag> php artisan about

Configuration

Recommended Swoole options in octane.php

// config/octane.php

return [
    'swoole' => [
        'options' => [
            'http_compression' => true,
            'http_compression_level' => 6, // 1 - 9
            'compression_min_length' => 20,
            'package_max_length' => 20 * 1024 * 1024, // 20MB
            'open_http2_protocol' => true,
            'document_root' => public_path(),
            'enable_static_handler' => true,
        ]
    ]
];

Utilities

Also, some useful Bash functions and aliases are added in utilities.sh that maybe help.

Notes

  • Laravel Octane logs request information only in the local environment.
  • Please be aware of .dockerignore content

ToDo

  • Add support for PHP 8.3
  • Add support for worker mode
  • Build assets with Bun
  • Create standalone and self-executable app
  • Add support for Horizon
  • Add support for RoadRunner
  • Add support for FrankenPHP
  • Add support for the full-stack apps (Front-end assets)
  • Add support testing environment and CI
  • Add support for the Laravel scheduler
  • Add support for Laravel Dusk
  • Support more PHP extensions
  • Add tests
  • Add Alpine-based images

Contributing

Thank you for considering contributing! If you find an issue, or have a better way to do something, feel free to open an issue, or a PR.

Credits

License

This repository is open-sourced software licensed under the MIT license.

laravel-octane-dockerfile's People

Contributors

gringodotdev avatar kichetof avatar michael-rubel avatar miladev95 avatar sloan58 avatar smortexa avatar tiagodevweb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-octane-dockerfile's Issues

AWS Fargate is replacing environment variables (AWS_*)

The issue comes when we're running the docker image in ECS.
it's replacing AWS_DEFAULT_REGION from eu-central-1 to eu-west-2

image

With FPM it loads the ENV normally
image

our .env file
image

So we're trying to access the S3 bucket which is hosted in a eu-central-1 region. and we're running ECS in eu-west-2

during install stoped

in first
docker build -t sampledoc:test .
enable sockets supports? [no] : enable json support? [no] : enable postgres support? [no] :
Even if I say no or yes, nothing happens

[Question] Octane supervisor

Considering I wanna spin up containers without any previous project, container Octane process will fail. Because octane tries to start through supervisor, and at this point there is no project yet.

My goal is:

  1. Spin up container
  2. Inside container run: laravel new app

I am looking for a way to not break containers with a fresh new Laravel app and avoid step 4.

Can't change `max_execution_time` value

Hi,
First of all thanks for all your work.
I'm facing a little issue, I don't know if it's expected or not : I can't change the value of max_execution_time in the php configuration.
I made the change in deployment/octane/php.ini file, but when the container is running and I run phpinfo(), I see max_execution_time is set to 0.
When running PHP from the command line the default setting is 0. From : https://www.php.net/manual/en/info.configuration.php#ini.max-execution-time
I'm able to change other PHP configuration like default_socket_timeout for example.

Also a last thing, not really related to your Dockerfile : When we run an artisan command, the boot and register methods of AppServiceProvider are triggered. Is it excepted ?

Thanks for the help !

Permission denied on laravel.log during start

I have a fresh laravel installation and added the files from this repo according to the instructions. The app won't start when running docker run.

2022-09-13 08:03:55,959 INFO spawned: 'octane_00' with pid 69

In StreamHandler.php line 146:

  The stream or file "/var/www/html/storage/logs/laravel.log" could not be op
  ened in append mode: Failed to open stream: Permission denied
  The exception occurred while attempting to log: The stream or file "/var/ww
  w/html/storage/logs/laravel.log" could not be opened in append mode: Failed
   to open stream: Permission denied
  The exception occurred while attempting to log: There are no commands defin
  ed in the "octane" namespace.
  Context: {"exception":{}}
  Context: {"exception":{}}

How to fix this? Is this a bug?

UPDATE: Nevermind, had to add octane via composer before and install it according to the laravel docs. Maybe add this requirement to the docs?

Add apt-get update for INSTALL_PG_CLIENT

Setting INSTALL_PG_CLIENT to true resulted for me in an error E: Unable to locate package postgresql-client-12.

I had to fix the Dockerfile accordingly:

RUN if [ ${INSTALL_PG_CLIENT} = true ]; then \
      . /etc/os-release \
      && echo "deb http://apt.postgresql.org/pub/repos/apt $VERSION_CODENAME-pgdg main" > /etc/apt/sources.list.d/pgdg.list \
      && curl -sL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
      && apt-get update \ # <-- NEW LINE
      && apt-get install -yqq --no-install-recommends --show-progress postgresql-client-12 postgis; \
      if [ ${INSTALL_POSTGIS} = true ]; then \
        apt-get install -yqq --no-install-recommends --show-progress postgis; \
      fi; \
  fi

Question regarding running app + horizon + scheduler

Hello!

First of all, congrats on this amazing project!

I have a very stupid question being kind of new to containerisation. I have a project running app, horizon and scheduler. What's the best approach to run the container(s)?

I've build the container using FrankenPHP. Do I need to run a container for each service (app,horizon,scheduler) separately? Or can it be done in a single container instance?

Best,
Tudor

doesnt work

$ docker build -t octane_test .
Sending build context to Docker daemon 21.5kB
Step 1/64 : ARG PHP_VERSION=8.1
Step 2/64 : ARG COMPOSER_VERSION=latest
Step 3/64 : FROM composer:${COMPOSER_VERSION} AS vendor
---> 0452f4d0ee68
Step 4/64 : WORKDIR /var/www/html
---> Using cache
---> bd8e9c0a8127
Step 5/64 : COPY composer* ./
COPY failed: no source files were specified


Step 53/63 : COPY . .
---> 6a63317adae9
Step 54/63 : COPY --from=vendor ${ROOT}/vendor vendor
COPY failed: stat var/www/html/vendor: file does not exist

error

failed to solve: failed to load cache key: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed

I have logged in to my docker hub account.

Cannot find module @rollup/rollup-linux-x64-musl

Thanks for the project! I'm learning a lot. I wanted to report an issue with the Vite build. I'm still trying to solve it, but here are the logs:

Laravel 10 + Filament

 => ERROR [laravel build 7/7] RUN npm run build                                                                                                                                                                                                0.7s 
------
 > [laravel build 7/7] RUN npm run build:
0.547
0.547 > build
0.547 > vite build
0.547
0.661 /var/www/html/node_modules/rollup/dist/native.js:87
0.661           throw new Error(
0.661                 ^
0.661
0.661 Error: Cannot find module @rollup/rollup-linux-x64-musl. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json and node_modules directory.  
0.661     at requireWithFriendlyError (/var/www/html/node_modules/rollup/dist/native.js:87:9)
0.661     at Object.<anonymous> (/var/www/html/node_modules/rollup/dist/native.js:96:76)
0.661     ... 3 lines matching cause stack trace ...
0.661     at Module._load (node:internal/modules/cjs/loader:1023:12)
0.661     at cjsLoader (node:internal/modules/esm/translators:356:17)
0.661     at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:305:7)
0.661     at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
0.661     at async ModuleLoader.import (node:internal/modules/esm/loader:329:24) {
0.661   [cause]: Error: Cannot find module '@rollup/rollup-linux-x64-musl'
0.661   Require stack:
0.661   - /var/www/html/node_modules/rollup/dist/native.js
0.661       at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)
0.661       at Module._load (node:internal/modules/cjs/loader:985:27)
0.661       at Module.require (node:internal/modules/cjs/loader:1235:19)
0.661       at require (node:internal/modules/helpers:176:18)
0.661       at requireWithFriendlyError (/var/www/html/node_modules/rollup/dist/native.js:69:10)
0.661       at Object.<anonymous> (/var/www/html/node_modules/rollup/dist/native.js:96:76)
0.661       at Module._compile (node:internal/modules/cjs/loader:1376:14)
0.661       at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
0.661       at Module.load (node:internal/modules/cjs/loader:1207:32)
0.661       at Module._load (node:internal/modules/cjs/loader:1023:12) {
0.661     code: 'MODULE_NOT_FOUND',
0.661     requireStack: [ '/var/www/html/node_modules/rollup/dist/native.js' ]
0.661   }
0.661 }
0.661

The "--audit" option does not exist.

Hi, when I build docker image I received this error message:

docker build -t app:1.0.15 .
=> ERROR [vendor 4/5] RUN composer install   --no-dev   --no-interaction   --prefer-dist   --ignore-platform-reqs   --optimize-autoloader   --apcu-autoloader   --  1.6s
 => CANCELED [stage-1  4/35] RUN apt-get update;     apt-get upgrade -yqq;     pecl -q channel-update pecl.php.net;     apt-get install -yqq --no-install-recommend  1.2s
------                                                                                                                                                                    
 > [vendor 4/5] RUN composer install   --no-dev   --no-interaction   --prefer-dist   --ignore-platform-reqs   --optimize-autoloader   --apcu-autoloader   --ansi   --no-scripts   --audit:                                                                                                                                                          
#0 1.574                                                                                                                                                                  
#0 1.582                                         
#0 1.582   The "--audit" option does not exist.  
#0 1.582                                         
#0 1.583 
#0 1.583 install [--prefer-source] [--prefer-dist] [--prefer-install PREFER-INSTALL] [--dry-run] [--dev] [--no-suggest] [--no-dev] [--no-autoloader] [--no-progress] [--no-install] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--apcu-autoloader-prefix APCU-AUTOLOADER-PREFIX] [--ignore-platform-req IGNORE-PLATFORM-REQ] [--ignore-platform-reqs] [--] [<packages>...]
#0 1.583 
------
Dockerfile:17
--------------------
  16 |     COPY composer* ./
  17 | >>> RUN composer install \
  18 | >>>   --no-dev \
  19 | >>>   --no-interaction \
  20 | >>>   --prefer-dist \
  21 | >>>   --ignore-platform-reqs \
  22 | >>>   --optimize-autoloader \
  23 | >>>   --apcu-autoloader \
  24 | >>>   --ansi \
  25 | >>>   --no-scripts \
  26 | >>>   --audit
  27 |     
--------------------
ERROR: failed to solve: process "/bin/sh -c composer install   --no-dev   --no-interaction   --prefer-dist   --ignore-platform-reqs   --optimize-autoloader   --apcu-autoloader   --ansi   --no-scripts   --audit" did not complete successfully: exit code: 1

I tried with --no-cache flag but it doesn't work too.

Default image

Is there any way to create a generic image with all library installations and leave the step of copying the vendor folder and other files in the project's Dockerfile? This would greatly reduce build and deploy time.

For example, in project dockerfile:

FROM my-images/laraswoole:v1.0.1

WORKDIR /var/www/html

COPY . .

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

RUN composer install \
  --no-dev \
  --no-interaction \
  --prefer-dist \
  --ignore-platform-reqs \
  --optimize-autoloader \
  --apcu-autoloader \
  --ansi \
  --no-scripts

RUN mkdir -p \
  storage/framework/{sessions,views,cache} \
  storage/logs \
  bootstrap/cache \
  && chown -R octane:octane \
  storage \
  bootstrap/cache \
  && chmod -R ug+rwx storage bootstrap/cache

COPY deployment/octane/supervisord* /etc/supervisor/conf.d/
COPY deployment/octane/php.ini /usr/local/etc/php/conf.d/octane.ini
COPY deployment/octane/opcache.ini /usr/local/etc/php/conf.d/opcache.ini

RUN chmod +x deployment/octane/entrypoint.sh
RUN cat deployment/octane/utilities.sh >> ~/.bashrc

EXPOSE 5000

ENTRYPOINT ["deployment/octane/entrypoint.sh"]

HEALTHCHECK --start-period=5s --interval=2s --timeout=5s --retries=8 CMD php artisan octane:status || exit 1

The my-images/laraswoole:v1.0.1 have all apt-get installs, etc.

Running container for development

Great work ,
Can you tell me how can i run this container for development
i added --watch flag to supervisor command and it throws this error :

==================Error==================
Error: Cannot find module 'chokidar'

Require stack:

- /var/www/html/api/laravel/vendor/laravel/octane/bin/file-watcher.js

    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)

    at Function.Module._load (node:internal/modules/cjs/loader:778:27)

    at Module.require (node:internal/modules/cjs/loader:1005:19)

    at require (node:internal/modules/cjs/helpers:102:18)

    at Object.<anonymous> (/var/www/html/api/laravel/vendor/laravel/octane/bin/file-watcher.js:1:18)

    at Module._compile (node:internal/modules/cjs/loader:1103:14)

    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1155:10)

    at Module.load (node:internal/modules/cjs/loader:981:32)

    at Function.Module._load (node:internal/modules/cjs/loader:822:12)

    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12) {

  code: 'MODULE_NOT_FOUND',

  requireStack: [

    '/var/www/html/api/laravel/vendor/laravel/octane/bin/file-watcher.js'

  ]

}
==================supervisord==================
[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/api/laravel/artisan octane:start --server=swoole --host=0.0.0.0 --port=9000 --workers=auto --task-workers=auto --max-requests=500 --watch

I added this code to Dockerfile but it doesnt work

=====================Dockerfile==================
=======================================
========= NODE  for octane --watch ==================
=======================================
RUN apt install -y nodejs
RUN apt install -y npm
RUN npm i -g chokidar

@smortexa
@tiagodevweb

Problem running container

Complaining about Class "Facade\Ignition\IgnitionServiceProvider" not found when running the container, I realized that this is a require-dev dependency and that --no-scripts doesn't enable @php artisan package:discover --ansi if you move for require dependencies, do you have any solution?

Zombie processes inside scheduler container for runInBackground() tasks

Initially I run scheduler inside app container and there was no problem with zombie processes. After I move scheduler to separate container, problem appered.

As I understand this process in simple words:
Laravel schedule:run spawn child process for each runInBackground() task and quits. Tasks become zombie (orphan processes = with no parent process) after completion, because supercronic (main init process in container) seems to doesn't know how to 'reap' orphan child processes or doesn't have to.

Screenshot 2024-01-13 at 04 36 01

More on PID 1 zombie reaping problem - https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/

My suggestion is to run scheduler container inside supervisord

start-container

...
elif [ ${container_mode} = "scheduler" ]; then
    initialStuff
    php artisan schedule:clear-cache
    # exec supercronic -overlapping /etc/supercronic/laravel
    exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.scheduler.conf
...

supervisord.scheduler.conf

[supervisord]
nodaemon=true
user=%(ENV_NON_ROOT_USER)s
logfile=/var/log/supervisor/supervisord.log
# use /var/log, because user has no write permissions to write to /var/run (symlink to /run)
pidfile=/var/log/supervisord.pid

[program:scheduler]
process_name=%(program_name)s_%(process_num)02d
command=supercronic -overlapping /etc/supercronic/laravel
user=%(ENV_NON_ROOT_USER)s
autostart=%(ENV_APP_WITH_SCHEDULER)s
autorestart=true
stdout_logfile=/var/www/html/scheduler.log

I checked this config, and it seems that problem is gone.

Not work.

2022-01-09 00:33:07,664 INFO Set uid to user 0 succeeded
2022-01-09 00:33:07,666 INFO supervisord started with pid 1
2022-01-09 00:33:08,668 INFO spawned: 'php_00' with pid 49


  There are no commands defined in the "octane" namespace.


2022-01-09 00:33:09,472 INFO exited: php_00 (exit status 1; not expected)
2022-01-09 00:33:10,475 INFO spawned: 'php_00' with pid 56


  There are no commands defined in the "octane" namespace.


2022-01-09 00:33:11,269 INFO exited: php_00 (exit status 1; not expected)
2022-01-09 00:33:13,273 INFO spawned: 'php_00' with pid 63


  There are no commands defined in the "octane" namespace.


2022-01-09 00:33:14,071 INFO exited: php_00 (exit status 1; not expected)
2022-01-09 00:33:17,076 INFO spawned: 'php_00' with pid 70


  There are no commands defined in the "octane" namespace.


2022-01-09 00:33:17,874 INFO exited: php_00 (exit status 1; not expected)
2022-01-09 00:33:18,875 INFO gave up: php_00 entered FATAL state, too many start retries too quickly

Why you using supervisor?

Using supervisor in container as main process is bad practice.
It req additional resources, it useless mediator via our app.
Why you not used only octane?

Scheduler issues - can't run overlapping tasks

Thanks for your work.

Faced 2 issues regarding Laravel scheduler:

  1. Can't run more than 1 job simultaneously. Reason is lack of -overlappingflag in supercronic start command (https://github.com/aptible/supercronic#duplicate-jobs).

Suggest to add this flag in supervisord.app.conf

[program:scheduler]
...
command=supercronic -overlapping /etc/supercronic/laravel
...
  1. Need to clear jobs mutexes in case of container restart.

Suggest to add to supervisord.app.conf one time process with autorestart=false

[program:clear-scheduler-cache]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan schedule:clear-cache
user=%(ENV_NON_ROOT_USER)s
autostart=%(ENV_APP_WITH_SCHEDULER)s
autorestart=false
stdout_logfile=/var/www/html/scheduler.log

Running as non root

If you want to switch the user to another user like octane in the Dockerfile

USER 1000:1000

Then this fails, is there away to run the php() function and the exec supervisord commands in entrypoint.sh as non root?

./deployment/octane/entrypoint.sh: no such file or directory: unknown

 => naming to docker.io/library/accounts_lumen                                                                  0.0s
Starting accounts ... error

ERROR: for accounts  Cannot start service lumen: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "./deployment/octane/entrypoint.sh": stat ./deployment/octane/entrypoint.sh: no such file or directory: unknown

ERROR: for lumen  Cannot start service lumen: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "./deployment/octane/entrypoint.sh": stat ./deployment/octane/entrypoint.sh: no such file or directory: unknown
ERROR: Encountered errors while bringing up the project.

The file exists in the docker folder still facing any issue
My Folder structure is as below.
accounts\docker\deployment\octane\entrypoint.sh

The below step works. If I rename entrypoint.sh file then it shows file not found in this step.
=> CACHED [stage-1 22/23] RUN chmod +x ./deployment/octane/entrypoint.sh

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.