Looking for new opportunities
I am looking for a new opportunities there for if you are looking for someone to join your team or you have something you want some help with feel free to reach out via email zaher[@]zah.me.
Warning !!
Please be aware that this is an old post, more than one year old, so you might need to look for an updated version of this article either on this site or using your favourite search engine.
What is Swoole
Before I can explain how you can install Swoole and use it with Laravel and Docker, I've to explain what is Swoole, and for that am going to quote the official explanation:
Production-Grade Async programming Framework for PHP, which enable PHP developers to write high-performance, scalable, concurrent TCP, UDP, Unix socket, HTTP, Websocket services in PHP programming language without too much knowledge about non-blocking I/O programming and low-level Linux kernel.
And they are doing a good job here by the way, now you can always check the official documentation for more about how it actually works, right now am going to show you how you can install it and use it with laravel, then I'll explain how you can dockerize your application in one image.
Install Swoole on linux:
There are two ways to install Swoole on your system, either using PECL or via source code:
Using PECL
It's simple and easy just run the following command:
#!/bin/bash
pecl install swoole
Build from sources:
It is recommended that you download the latest stable version from Github or from PECL, then execute the following commands:
PS: I'll be downloading the code from Github, and by the time of writing version 4.2.8 is the latest stable one.
$ wget -c https://github.com/swoole/swoole-src/archive/v4.2.8.tar.gz -O swoole.tar.gz
$ tar -xvzf swoole.tar.gz
$ cd swoole-src-4.2.8
$ phpize # prepare the build environment for a PHP extension
$ ./configure # add configuration paramaters as needed
$ make # a successful result of make is swoole/module/swoole.so
$ sudo make install # install the swoole into the PHP extensions directory
If you are planning to build it from source, I would recommend that you check the configuration options.
Enable swoole extension:
Now that we have installed swoole, it's time for us to enable the extension, and this can be done by simple loading
the extension via php.ini
like the following:
php -i | grep php.ini # check the php.ini file location
sudo echo "extension=swoole.so" > php.ini # add the extension=swoole.so to the end of php.ini
php -m | grep swoole # check if the swoole extension has been enabled
Another option would be to create a new ini
file under the conf.d
directory for the installed php on the system.
Installing Laravel and Laravel-Swoole package
Basically you can just run composer create-project
command to create a new project using laravel like:
$ composer create-project laravel/laravel swoole
After composer
finish, we just need to install laravel-swoole package by running the following command:
$ composer require swooletw/laravel-swoole
Configure Lravel-Swoole package
If you are using anything before laravel 5.6 you will need to load the service provide manually:
[
'providers' => [
SwooleTW\Http\LaravelServiceProvider::class,
],
]
Otherwise, Laravel will autoload it for you.
If you want to change the default configurations, you can run the publish command which will generate two configuration file that you can modify
$ php artisan vendor:publish --tag=laravel-swoole
You can read more about the configuration part on the package wiki page.
Run laravel-Swoole
Now that everything is setup, you can run Swoole server by executing the command:
$ php artisan swoole:http start
Which will load the configuration from the config files and start your server, by default it will run on http://127.0.0.1:1215
.
There are few more commands that you can use with swoole:http
, feel free to check them:
$ php artisan swoole:http {start|stop|restart|reload|infos}
Command | Description |
---|---|
start |
Start Laravel Swoole, list the processes by ps aux|grep swoole |
stop |
Stop Laravel Swoole |
restart |
Restart Laravel Swoole |
reload |
Reload all worker process(Contain your business & Laravel/Lumen codes), excluding master/manger process |
infos |
Show PHP and Swoole basic miscs infos(including PHP version, Swoole version, Laravel version, server status and PID) |
Just remember that The swoole_http_server can only run in cli environment
, so the artisan command helps you to manage it.
The support of swoole_http_server for Http is not complete. So, you should configure the domains via nginx proxy in your production environment. You can check the wiki for more information about it.
Dockerizing your application:
There are a lot of tutorials out there talking about how to dockerize your application, so am not going to go into deep details about the process.
In general we should have a Dockerfile
which have all the steps that we need, so basically your Dockerfile
should have:
- PHP 7.x.
- Swoole.
- Nginx (optional, just keep reading).
The main advice which everyone miss to say, is that you should build a base image that you can always use so you dont repeat the build and wait to have everything in your image every time you run build it.
Based on this, I already have built a docker image which has Swoole installed, enabled and ready to use with PHP 7.2 and Composer, you can find it here.
Remember to add any environment variables you need to your .env.example
file so every person in your team will be able
to use them and be notified when changed, as an example I have added the two environment variables to the file in my
code
SWOOLE_HTTP_PORT=80
SWOOLE_HTTP_HOST=0.0.0.0
And you will see next how I use them in my Docker image.
Dockerfile content
So first lets have our Dockerfile
at the root of our Laravel application, and it will contain the following:
FROM zaherg/php-swoole:7.2
LABEL Maintainer="Zaher Ghaibeh <z@zah.me>"
ENV APP_NAME ${APP_NAME:-laravel}
ENV APP_ENV ${APP_ENV:-production}
ENV APP_KEY ${APP_KEY}
ENV APP_DEBUG ${APP_DEBUG:-false}
ENV APP_URL ${APP_URL:-"http://localhost"}
ENV LOG_CHANNEL ${LOG_CHANNEL:-stack}
ENV APP_TIMEZONE ${APP_TIMEZONE:-UTC}
ENV DB_CONNECTION ${DB_CONNECTION:-mysql}
ENV DB_HOST ${DB_HOST:-database}
ENV DB_PORT ${DB_PORT:-3306}
ENV DB_DATABASE ${DB_DATABASE:-docker}
ENV DB_USERNAME ${DB_USERNAME:-docker}
ENV DB_PASSWORD ${DB_PASSWORD:-secret}
ENV DB_COLLATION ${DB_COLLATION:-utf8mb4_unicode_ci}
ENV DB_CHARSET ${DB_CHARSET:-utf8mb4}
ENV BROADCAST_DRIVER ${BROADCAST_DRIVER:-log}
ENV CACHE_DRIVER ${CACHE_DRIVER:-file}
ENV QUEUE_CONNECTION ${QUEUE_CONNECTION:-sync}
ENV SESSION_DRIVER ${SESSION_DRIVER:-file}
ENV SESSION_LIFETIME ${SESSION_LIFETIME:-120}
ENV REDIS_HOST ${REDIS_HOST:-"127.0.0.1"}
ENV REDIS_PORT ${REDIS_PORT:-6379}
ENV REDIS_PASSWORD ${REDIS_PASSWORD:-null}
ENV MAIL_DRIVER ${MAIL_DRIVER:-smtp}
ENV MAIL_HOST ${MAIL_DRIVER:-smtp.mailtrap.io}
ENV MAIL_PORT ${MAIL_PORT:-2525}
ENV MAIL_USERNAME ${MAIL_USERNAME:-null}
ENV MAIL_PASSWORD ${MAIL_PASSWORD:-null}
ENV MAIL_ENCRYPTION ${MAIL_ENCRYPTION:-null}
ENV PUSHER_APP_ID ${PUSHER_APP_ID}
ENV PUSHER_APP_KEY ${PUSHER_APP_KEY}
ENV PUSHER_APP_SECRET ${PUSHER_APP_SECRET}
ENV PUSHER_APP_CLUSTER ${PUSHER_APP_CLUSTER}
ENV MIX_PUSHER_APP_KEY ${PUSHER_APP_KEY:-""}
ENV MIX_PUSHER_APP_CLUSTER ${PUSHER_APP_CLUSTER:-""}
ENV SWOOLE_HTTP_PORT ${SWOOLE_HTTP_PORT:-80}
ENV SWOOLE_HTTP_HOST ${SWOOLE_HTTP_HOST:-"0.0.0.0"}
USER root
ADD ./ /var/www
RUN composer global require hirak/prestissimo && \
composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
CMD ["php", "artisan","swoole:http","start"]
In the first line, we specify our base image, which as I said has Swoole and PHP 7.2:
FROM zaherg/php-swoole:7.2
From line 5 till line 42 we define the default our environment variables, which as you can notice all from the .env.example
file in laravel, except the last two one which is related to Swoole.
Then we copy our code over to the Docker image, and run composer install.
The last line is the most important one, as we use it to start Swoole once the image is ready
CMD ["php", "artisan","swoole:http","start"]
To clean up the build process for Docker, we will create .dockerignore
file which will contain the following:
/.git
/bin
/vendor
Building the image:
As any docker image, to build it we should run the following command:
docker build -t laravel-swoole:latest .
Running your image
Running the image is simple, all you have to do is to execute the following command:
docker run -p 80:80 laravel-swoole:latest -d
And open your browser type http://localhost
and you should be greeting with the default laravel homepage.
Now that you have your image, you can deploy it and put it behind Nginx or any Proxy server and it will work.
Utilizing Traefik
Now that we have everything we need, lets raise the bar a bit and use Traefik as our
proxy in-front of our Laravel application, am not going to go into details, but I'll share my docker-compose.yml
file:
version: "3.6"
services:
app:
image: laravel-swoole
build:
context: ./
dockerfile: Dockerfile
networks:
- backend
volumes:
- ./:/var/www
labels:
- "traefik.backend=web"
- "traefik.frontend.rule=Host:web.docker.local"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.backend.loadbalancer.method=drr"
healthcheck:
disable: true
env_file:
- .env
restart: unless-stopped
database:
image: mysql:5.7
hostname: database
ports:
- "3306:3306"
environment:
- "MYSQL_RANDOM_ROOT_PASSWORD=yes"
- "MYSQL_DATABASE=docker"
- "MYSQL_USER=docker"
- "MYSQL_PASSWORD=secret"
networks:
- backend
volumes:
- mysql:/var/lib/mysql
labels:
- "traefik.backend=database"
- "traefik.enable=false"
restart: unless-stopped
proxy:
image: traefik:latest
command:
- --web
- --web.statistics
- --docker
- "--docker.domain=docker.local"
- "--docker.swarmMode=false"
- "--logLevel=DEBUG"
- --defaultentrypoints=web
- "--entryPoints=Name:web Address::80 Compress:true"
networks:
- backend
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
labels:
- "traefik.backend=proxy"
- "traefik.frontend.rule=Host:proxy.docker.local"
- "traefik.enable=true"
- "traefik.port=8080"
restart: unless-stopped
networks:
backend:
volumes:
mysql:
Final words
As you can see it is so simple to have your application dockerized and run by the help of few tools, and using Swoole within your code will give you a big advantages in speed.
Lastly, to make things simpler, I've created two starter projects that you can use as a template for your when building laravel or lumen application and you want to try swoole, you can get them from packagist :