Рецепты Docker: Monkey patch

от автора


Настройка локально

Начало: habrahabr.ru/post/267441

В этой статье я предполагаю, что служба docker запущена на той же машине, на которой выполняются команды, и у процесса есть доступ на чтение к текущей папке. Еще я подразумеваю, что вы умеете настраивать связку PHP-FPM и Nginx.

Беру образы Nginx и PHP 7.

~$ docker pull nginx ... ~$ docker pull php:7-fpm Status: Downloaded newer image for php:7-fpm 

Теперь у меня есть два чужих класса, которые надо связать вместе через внедрение зависимостей. Самый простой способ добавлять зависимости в чужой код, конечно же, monkeypatching! Сначала создаю контейнеры. Помню о второй сложности программирования — даю контейнерам вразумительные имена, они будут нужны, чтобы контейнеры могли взаимодействовать между собой.

~$ docker create --name=php7 php:7-fpm 3d1b737edfcc3f1102fa54c91f9120da4b86d8cbba3092b6f80156c0e31b4d8f ~$ docker create --name=nginx nginx 80be81b27e012fd061ff4b682f0b7b8803500bc38a4b9f787f91661603b2d4b7 

PHP

Начну с PHP — его настроить сложнее. Где лежат конфиги для PHP — можно увидеть в его Dockerfile:

    ENV PHP_INI_DIR /usr/local/etc/php        --with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \     WORKDIR /var/www/html     COPY php-fpm.conf /usr/local/etc/ 

Копирую себе из контенера содержимое каталога с файлами конфигурации php

~$ mkdir monkeypatch ~$ cd monkeypatch/ $ docker cp php7:/usr/local/etc localetc $ ls localetc/ pear.conf        php            php-fpm.conf        php-fpm.conf.default    php-fpm.d $ ls localetc/php conf.d 

Мейнтейнеры положили в образ php-fpm.conf, но не положили дефолтный php.ini. Придется взять его из исходников php.

$ docker cp "$PHP7:/usr/src/php/php.ini-development" localetc/php/php.ini 

Правлю конфиги, как обычно. В какой папке PHP ищет расширения? Узнать можно, запустив php, например, во временном контейнере.

$ docker run --rm php:7-fpm php -i |grep extension_dir extension_dir => /usr/local/lib/php/extensions/no-debug-non-zts-20141001 => /usr/local/lib/php/extensions/no-debug-non-zts-20141001 $ docker run --rm php:7-fpm ls /usr/local/lib/php/extensions/no-debug-non-zts-20141001 opcache.a opcache.so 

В расширениях только opcache, можно подключить его.

$ echo extension_dir = "/usr/local/lib/php/extensions/no-debug-non-zts-20141001" >>  localetc/php/php.ini $ echo zend_extension = opcache.so >> localetc/php/php.ini 

Пересоздаю контейнер php и монтирую в него папку с конифгами. Путь к монтируемой папке должен быть от корня — служба не знает, из какой папки вызывается клиент docker.

$ docker rm php7 php7 $ docker run -v "$(pwd)/localetc:/usr/local/etc" --name=php7 php:7-fpm php -i |grep Configuration Configuration File (php.ini) Path => /usr/local/etc/php Loaded Configuration File => /usr/local/etc/php/php.ini 

Теперь можно пересоздать контейнер php7 с тестовым приложением на php. Создатели образа не позаботились о том, чтобы php-fpm работал как демон, так что надо самим запускать его фоном, не освобождая стандартные каналы ввода-вывода.

$ docker rm php7 $ mkdir scripts $ echo " scripts/test.php $ docker run -v "$(pwd)/localetc:/usr/local/etc" \     -v "$(pwd)/scripts:/scripts" \     --name=php7 php:7-fpm & [29-Aug-2015 15:19:25] NOTICE: fpm is running, pid 1 [29-Aug-2015 15:19:25] NOTICE: ready to handle connections 

Пока что для удобства отладки я оставляю вывод из контейнера php-fpm в свою консоль.

NGINX

С Nginx всё просто и стандартно. Копирую на диск папку конфигов:

$ docker cp nginx:/etc/nginx . 

В папке nginx/ надо отредактировать nginx.conf, fastcgi_params по вкусу, и создать конфигурационный файл для своего сайта в nginx/conf.d/. Основное для связи nginx с php — это указать в имени хоста имя контейнера с php, а директивы root и SCRIPT_FILENAME должны указывать на путь, который php поймёт в своём контейнере php7.

    location ~ \.php$ {         fastcgi_pass   php7:9000;         fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name; 

Монтирую конфиги в контейнер nginx и запускаю с маппингом 80-го порта контейнера на локальный 8080.

$ docker rm nginx $ docker run -v "$(pwd)/nginx:/etc/nginx" -p 8080:80 --name=nginx nginx & $ curl 127.0.0.1:8080/test.php 172.17.0.65 -  29/Aug/2015:15:50:29 +0000 "GET /test.php" 200 Hello world! 7.0.0RC1 

Rock’n’Roll!

В версии 1.7 в команде docker run надо указывать параметр —link чтобы в контейнере резолвилось имя другого контейнера. В версии 1.8.1 все работает и без этого параметра.

Логи

Мейнтейнеры образа php решили писать все логи fpm в /proc/self/fd/2, он же STDERR — как error_log, так и access.log. Однако, лог запросов у меня будет писать nginx, а в работе php меня интересуют только ошибки, поэтому предлагаю отредактировать localetc/php-fpm.conf и написать что-то привычное:

error_log = /var/log/php/php-fpm.error.log ;access.log = /proc/self/fd/2  

В Nginx обошлись без самодеятельности, так что включаю access log в конфиге сайта nginx/conf.d/site.ru.conf

access_log  /var/log/nginx/host.access.log  main; 

Теперь можно создать папку для логов c правом записи для демона docker и подмонтировать ее в контейнеры. В эту же папку можно писать и вывод контейнеров, при этом контейнеры можно детачить:

$ mkdir log $ sudo chgrp docker log/ $ sudo chmod g+rwx log/ $ docker stop nginx php7 $ docker rm nginx php7 $ docker run -d --name=php7 \     -v "$(pwd)/localetc:/usr/local/etc" \     -v "$(pwd)/scripts:/scripts" \     -v "$(pwd)/log:/var/log/php" \     php:7-fpm >>log/docker.php.log 2>&1 $ docker run -d --name=nginx \     -v "$(pwd)/nginx:/etc/nginx" \     -v "$(pwd)/log:/var/log/nginx" \     -p 8080:80 \     nginx >>log/docker.nginx.log 2>&1 $ curl 127.0.0.1:8080/test.php Hello world! 7.0.0RC1 

Когда надо поменять конфигурацию — можно дать команду перезагрузки php и nginx.

$ docker exec php7 pkill -o -USR2 php-fpm $ docker exec nginx service nginx reload Reloading nginx: nginx. 

Когда php 7 будет включен в дистрибутив Debian в образе php:7 появится init-скрипт. При желании, можно добавить его самостоятельно из дистрибутива по выбору.

ссылка на оригинал статьи http://habrahabr.ru/post/267455/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *