Webserver Docker alapokon -2.rész (PHP-FPM:7.3-alpine)

Ebben a bejegyzésben megismerkedünk a docker php7.3-fpm OFFICIAL verziójával, alpine linux alapokon. Bemutatom, hogy hogyan lehet az alap image -hez hozzáadni további-, az official változat által nem aktív modulokat. A project bemutatását egy alap debian10 (buster) linuxon mutatom be.

Image beszerzése

A docker hub-on számos közösségi- és hivatalos image megtalálható. Sőt, akár regisztrálhatunk is a https://hub.docker.com/ oldalon, így lehetőségünk van, akár saját image-k feltöltésére és terjesztésére is. Most azonban keressük meg a leírás tárgyát képező verziót, az egyszerűség kedvéért ide linkelem az oldalt. Készítsünk egy munkakönyvtárat, mondjuk /home/Docker néven:

mkdir -p /home/Docker
cd /home/Docker

Szerdjük le az image-t:

docker pull php:7.3-fpm-alpine

Töltsük le ebbe a könyvtárba az Dockerfile-t és az összes scriptet és az utóbbiaknak adjunk futtatási jogot:

chmod +x docker-php-*

Majd build-eljük az image-ünket. Ez a folyamat hosszú ideig is eltarthat, hoszen a php kiválasztott verziója forrásból kerül az alpine linuxhoz:

docker build -t php:7.3-alpine .

Miután a folyamat véget ért, ellenőrizzük, hogy milyen modulok kerültek az imege-be, alapértelmezés szerint:

docker run -ti --rm php:7.3-alpine -m

Bővebb információt az alábbi paranccsal kaphatunk:

docker run -ti --rm php:7.3-alpine -i

Jelen helyzetben azt kell eldöntenünk, hogy milyen egyéb modulra lenne szükségünk. Én a leírás szerint fogok választani. Indítsunk egy terminált:

docker run -ti --rm php:7.3-alpine /bin/sh

Frissítsük a csomaginformációkat:

apk update

A további modulokat, melyeket forrásból telepíthetünk a következő utasítással kapjuk meg:

docker-php-source extract

A modulok könyvtára:

/usr/src/php/ext/

Amire még szükségünk lehet:

apk add --virtual .build-deps git freetype-dev libjpeg-turbo-dev libmcrypt-dev libpng-dev libxml2-dev

Az egyes moduloknak lehetnek a fordításra vonatkozóan további jellemzőjük, melyet be kell állítani. Ilyen például a gd, aminek a használatához szükséges library-k a /usr/lib könyvtárban- és nem a /usr/local/lib könyvtárba vannak.

docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr

Szükségünk lesz továbbá a session információk tárolásához a redis-re, melynek a telepítése:

git clone https://github.com/phpredis/phpredis.git /usr/src/php/ext/phpredis

Adjuk hozzá az egyes modulokat az image-nkhöz:

docker-php-ext-install mysqli opcache gd bcmath soap phpredis

A következő paranccsal megkapjuk azokat a csomagokat, melyek szükségesek a felvett modulok működéséhez. Tegyük be ezeket egy változóba. Ezek kelleni fogknak a későbbiekben is. A .build-deps azokat a csomagokat tartalmazza, melyek a fordításhoz szükségesek, de a működéshez nem kellenek. Ezeket el is távolíthatjuk később.

phpdeps=$(scanelf --needed --nobanner --recursive /usr/local/lib/php/extensions |awk '{ gsub(/,/,"\
nso:", $2); print "so:" $2 }' | sort -u | xargs -r apk info --installed | sort -u)

Adjuk is hozzá ezeket azokhoz a virtuális csomagokhoz, melyek már a korábbi telepítéskor mentésre kerültek:

apk add --virtual .phpexts-rundeps $phpdeps

Most pedig töröljük a korábban említett átmeneti csomagokat, illetve az ext könyvtárban lévő további modulokra sincs szükség:

apk del .build-deps && docker-php-source delete

Ellenőrizzük le, hogy a modulok valóban hozzáadásra kerültek e a korábbiakhoz:

php -m, vagy php-fpm -m

Dockerfile

Amennyiben minden rendben, a fenti műveleteket felhasználva elkészítjük a Dockerfile-t, hogy ezeket a lépéseket automatizálni tudjuk, tehát a véredemény így néz ki:

nano Dockerfile
FROM php:7.3-fpm-alpine
MAINTAINER Albert Vanyi <albert@vanyi.eu>

RUN apk update \
&& apk add zip unzip \
&& apk add --virtual .build-deps git freetype-dev libjpeg-turbo-dev libmcrypt-dev libpng-dev libxml2-dev \
&& docker-php-source extract \
&& git clone https://github.com/phpredis/phpredis.git /usr/src/php/ext/phpredis \
&& docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \
&& docker-php-ext-install mysqli opcache gd bcmath soap phpredis \
&& phpdeps=$(scanelf --needed --nobanner --recursive /usr/local/lib/php/extensions |awk '{ gsub(/,/,"\ nso:", $2); print "so:" $2 }' | sort -u | xargs -r apk info --installed | sort -u)
&& apk add --virtual .phpexts-rundeps $phpdeps \
&& apk del .build-deps \
&& docker-php-source delete

COPY etc/ /usr/local/etc/

# A php magát menedzseli, a -F foreground előtérben fut
CMD ["/usr/local/sbin/php-fpm","-F"]

Konfiguráció

Amint látható az eredeti php konfigurációt felülírom a saját verziómmal, készítsük el ezeket most.

mkdir -p etc/php/conf.d && mkdir -p etc/php/php-fpm.d

Lépjünk a conf.d könyvtárba:

cd etc/php/conf.d

Hozzuk létre a következő állományokat:

nano assertion.ini
[Assertion]
; Kikapcsoljuk az assertion-t
zend.assertions = -1
nano global.ini
[global]
engine = On
rlimit_core = 0
display_errors = Off
display_startup_errors = Off
track_errors = Off
log_errors = On
error_log = /dev/stderr
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
; Globális változót csak akkor regisztrál a php, ha valaki hivatkozik rá
auto_globals_jit = On
short_open_tag = Off
precision = 14
; Hasznos lehet worpress-nél a rosszul megírt programoknál a http headering változtatás miatt
output_buffering = 8192
zlib.output_compression = On
disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtersig,pcntl_wstopsig,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority
zend.enable_gc = On
expose_php = Off
max_execution_time = 600
max_input_time = 300
memory_limit = 256M
post_max_size = 100M
file_uploads = On
upload_max_filesize = 100M
max_file_uploads = 20
default_mimetype = "text/html"
default_charset = "UTF-8"
enable_dl = Off
;Nem ajánlott, de a wordpress-nek kell
allow_url_fopen = On
allow_url_include = On
default_socket_timeout = 300
nano mysqli.ini
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_local_infile = Off
mysqli.allow.persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host = mysql
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
nano opcache.ini
[opcache]
opcache.enable=1
opcache.memory_consumtion=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=2
opcache.fsst_shutdown=1
;Érdemes beállítani fájl cache esetén a fájl teljes elérési útját cache-li, nem csak a fájlnevet
opcache.use_cwd=1
nano session.ini
[Session]
;session.save_handler = files #Virtualhostok esetén érdemes beállítani
;session.save_path = /var/tmp #Virtualhostok esetén ide mentődnek az adatok
session.save_handler = redis
session.save_path = "tcp://redis:6379?weight=1"
session.use_strict_mode = On
;session.use_cookies = On
;session.cookie_secure = On
session.use_only_cookies = On
session.cookie_httponly = On
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = Off

Majd lépjünk át a másik-, php-fpm.d könyvtárunkba:

cd ../php-fpm.d

Hozzuk létre a www.conf fájlt:

nano www.conf
[global]
emergency_restart_threshold = 30
emergency_restart_interval = 10m
process_control_timeout = 5m

[www]
user = www-data
group = www-data
pm = dynamic
pm.max_children = 200
pm.start_servers = 50
pm.min_spare_servers = 20
pm.max_spare_servers = 50
pm.process_idle_timeout = 30s
pm.max_requests = 200
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
slowlog = /dev/stderr
request_slowlog_timeout = 5m
request_terminate_timeout = 1h

Konklúzió

A konfigurációban látható, hogy a beállítások között mysql adatbáziskezelőt és redis szerver konfigurációt is megadtam. Ahhoz, hogy megfelelően működjön a php motor, természetesen ezeket az alkalmazás szervereket is elérhetővé kell tennünk, A folytatásban erre fogok kitérni.