Оптимизация конфигурации Dockerfile в PHP

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В настоящее время все работает лучше при использовании Docker для настройки локальных сред, а не при локальной установке PHP и других зависимостей. Когда начинаются новые PHP-проекты, Dockerfiles (Docker-файлы) копируются из одной кодовой базы в другую, поскольку для запуска каждого проекта требуются схожие базовые зависимости. Это существенно затрудняет поддержку изменений в контейнерах.

Чтобы избежать этого, в TeleSoftas возникла идея иметь простой базовый образ, который упростил бы разработку и сопровождение наших проектов. Этот образ опубликован на DockerHub, что облегчает запуск нового проекта за счет сокращения объема необходимого кода.

Решение

Давайте рассмотрим базовый образ PHP Dockerfile, необходимый для запуска приложения Symfony:

FROM php:8.1-fpm-alpine  

RUN addgroup -g 1000 -S app && \  
    adduser -u 1000 -S app -G app  

RUN apk add \  
    autoconf \  
    build-base \  
    git  

RUN docker-php-ext-install pdo_mysql  

RUN pecl install apcu-5.1.21  
RUN docker-php-ext-enable apcu opcache  

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

Мало того, эта простая конфигурация работает и для обычных PHP-проектов, и для Laravel. Копировать один и тот же Dockerfile и поддерживать его во всех проектах становится немного сложно и запутанно, так почему бы не сделать это проще?

Публикация образа на Dockerhub

Чтобы не создавать новый Dockerfile для каждого проекта, вы можете опубликовать его на DockerHub и потом получить через docker-compose.yml прямо оттуда. А создание образа не сложнее нескольких команд — войдите в свой аккаунт на DockerHub, соберите образ и отправьте его.

docker login -u <YOUR_DOCKERHUB_USERNAME> -p <YOUR_DOCKERHUB_TOKEN> docker.io
docker build -t index.docker.io/<YOUR_DOCKERHUB_USERNAME>/php:8.1 .
docker push index.docker.io/<YOUR_DOCKERHUB_USERNAME>/php:8.1

Использование только что созданного образа

Сначала создайте файл docker-compose.yml со следующей конфигурацией службы:

version: '3.7'  

services:  
    php:  
        image: <YOUR_DOCKERHUB_USERNAME>/php:8.1
        user: app  
        volumes:  
            - ./app:/srv/app

Теперь вы можете просто игнорировать сборку образа локально, он будет извлекаться из DockerHub. Таким образом, вы избежите дублирования Dockerfile в разных проектах и упростите его поддержку.

Это полезно при создании нового проекта Symfony/Laravel с нуля или, например, при локальном выполнении PHP-кода, поскольку Docker в настоящее время более популярен, чем наличие всех библиотек на вашей хост-машине.

Расширение Dockerfile для каждого проекта

Иногда вам нужны некоторые зависимости в одном проекте и не нужны в другом. Это также легко сделать, используя новый опубликованный образ. Например, в некоторых проектах при локальной разработке вам может понадобиться XDebug или другие дополнительные библиотеки. Для решения этого можно создать небольшой Dockerfile, который будет извлекать базовый образ и добавлять поверх него необходимые библиотеки.

FROM <YOUR_DOCKERHUB_USERNAME>/php:8.1  

RUN pecl install xdebug-3.1.1
RUN docker-php-ext-enable xdebug

Далее разверните свою конфигурацию docker-compose.yml:

version: '3.7'  

services:  
    php:  
        build: .  
        user: app  
        volumes:  
            - ./app:/srv/app

И все предельно просто. Нет дублирования кода, а основные зависимости легко поддерживать во всех проектах. Вы можете добавить столько пользовательских настроек в этот локальный Dockerfile, сколько вам нужно.

Автоматизация публикации в Dockerhub

Допустим, вам нужно обновить Composer (пакетный менеджер для PHP) до более новой версии в вашем базовом образе. Для этого нужно обновить наш Dockerfile, зайти на DockerHub, собрать образ и опубликовать его. Вы можете упростить эту задачу, автоматизировав этапы сборки и публикации вашего пайплайна.

Для этого руководства я выбрал GitLab в качестве репозитория исходного кода и создал файл .gitlab-ci.yml со следующей конфигурацией для автоматизации всего процесса

stages:  
    - build  

variables:  
    IMAGE_VERSION: '8.1'  

build:  
    stage: build  
    image: docker:latest  
    before_script:  
        - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"  "$CI_REGISTRY"  
    script:  
        - docker build --pull -t $CI_REGISTRY_IMAGE:$IMAGE_VERSION .  
        - docker push $CI_REGISTRY_IMAGE:$IMAGE_VERS

Остался только один шаг — определить переменные в настройках CI/CD проекта:

CI_REGISTRY=docker.io  
CI_REGISTRY_IMAGE=index.docker.io/<YOUR_DOCKERHUB_USERNAME>/php
CI_REGISTRY_USER=<YOUR_DOCKERHUB_USERNAME>  
CI_REGISTRY_PASSWORD=<YOUR_DOCKERHUB_TOKEN>

Когда вы отправляете обновленный образ на GitLab, он будет собран и помещен в DockerHub после завершения пайплайна. Эту конфигурацию можно легко адаптировать к Bitbucket или Github, руководствуясь их инструкциями по настройке пайплайна.

Резюме

Осталось только выполнить один большой шаг — решить, что требуется в вашем базовом образе, собрать его и опубликовать на DockerHub. И вот что мы сделаем:

  1. Создайте два репозитория для Docker-образов PHP 8.0 и 8.1.

  2. Создайте Dockerfile и добавьте конфигурацию CI, чтобы автоматизировать весь процесс.

  3. Тегируйте образ и отправьте его в реестр образов в DockerHub после завершения пайплайна. И все. Вот так вы можете значительно упростить свою разработку.

Это принесет пользу не только существующим, но и новым проектам. Облегчается поддержка всех приложений - если для работы последней версии Symfony требуется новая библиотека или пакет, достаточно один раз обновить базовый образ и он уже будет доступен во всех проектах.

Идем дальше

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


Работая с PHP продолжительное время, мы рано или поздно сталкиваемся с задачами, которые выходят за рамки обработки HTTP-запросов здесь и сейчас, а требуют более комплексных решений. Это могут быть обработки большого объема данных, прослушивание событий и так далее. Конечно, можно взять и внедрить ещё один язык в стек, но это подходит далеко не всем. Приглашаем на открытое занятие, на котором разберемся с тем, как PHP может решать задачи подобного рода. Регистрация — по ссылке.

Источник: https://habr.com/ru/company/otus/blog/674952/


Интересные статьи

Интересные статьи

dotMemory — это профилировщик памяти для .NET от компании JetBrains. А меня зовут Илья, и я из команды разработки этого инструмента.Хочу поделиться историей классического догфудинга: как мы оптимизиро...
Все «за» и «против» 1С-Битрикс, какие есть альтернативы и что выгоднее знать разработчику? Читать далее
В прошлой части мы поговорили о советах директору по разработке бизнес-процесса в Битрикс24, сейчас же я постараюсь дать советы руководителям отделов, поскольку по моему опыту почти всегд...
Доброго времени суток, уважаемые хабровчане. Сегодня речь пойдет опять и снова про mySQL. Разберемся в оптимизации и поговорим про множество параметров сервера. Давайте приступать. ...
Есть несколько способов добавить водяной знак в Битрикс. Рассмотрим два способа.