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.