Symfony кеш: очистить при создании контейнера docker или при первом запуске? - PullRequest
0 голосов
/ 20 апреля 2020

Я контейнер symfony -3 приложения в docker.

В настоящее время я копирую полный parameters.yml в функции сборки ARG, поэтому я могу сделать 3 различные сборки: devel, pre и prod с 3 различными файлами конфигурации.

Я уже знаю, что правильный путь к go будет для одной сборки , следовательно, один двоичный файл скомпилированного образа для всех сред, а затем при запуске контейнера передайте всю конфигурацию через переменные ENV. Но мне нужно go с копированием конфигурации.

У меня есть это к концу моего Dockerfile:

ARG ENVIRONMENT

# Copy the config file.
COPY config/tighten-violet.parameters.${ENVIRONMENT}.yml /files/tighten-violet/app/config/parameters.yml

# Build the composer part
RUN \
    cd /files/tighten-violet && \
    composer --no-ansi --no-interaction install --no-progress  --no-autoloader --no-scripts && \
    composer --no-ansi --no-interaction dump-autoload --no-dev --optimize --classmap-authoritative --no-scripts && \
    composer --no-ansi --no-interaction run-script --no-dev symfony-scripts && \
    php bin/console cache:clear && \
    php bin/console cache:clear --env=prod && \
    php bin/console assetic:dump --env=prod && \
    :

EXPOSE 80

# Start apache
CMD [ "apachectl", "-D", "FOREGROUND" ]

Бывает, что хост "builder" не предоставляет подключение к производственным базам данных ... и теперь я удивлен, что при очистке кэша я вижу, что есть "реальное соединение" с базой данных. Я думал, что кеш имеет отношение только к "stati c разбору кода" для компиляции автозагрузчика, компиляции сервис-контейнеров и так ...

Я получаю эту ошибку:

Updating the "app/config/parameters.yml" file
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache

 // Clearing the cache for the dev environment with debug
 // true

 [OK] Cache for the "dev" environment (debug=true) was successfully cleared.

  [Doctrine\DBAL\Exception\ConnectionException]
  An exception occured in driver: SQLSTATE[HY000] [2002] Connection timed out

  [Doctrine\DBAL\Driver\PDOException]
  SQLSTATE[HY000] [2002] Connection timed out

  [PDOException]
  SQLSTATE[HY000] [2002] Connection timed out

cache:clear [--no-warmup] [--no-optional-warmers] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] <command>

Script Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache handling the symfony-scripts event terminated with an exception

[...]

Похоже, что symfony-scripts запускает Sensio Bundle, который по какой-либо причине пытается установить реальное соединение.

Вопрос

Если я хочу инкапсулировать полностью настроено приложение symfony -3 внутри docker, нужно ли запускать сценарии во время сборки? Или я должен как-то запустить их как часть сценария входа точки запуска, который сначала запускает сценарии, а затем запускает apache?

1 Ответ

0 голосов
/ 21 апреля 2020

Решение состоит в том, чтобы разделить composer часть на 2 отдельных блока:

Блок 1 из composer инструкций

Часть, которая загружает пакеты. Это может выполняться внутри «компоновщика».

Блок 2 из composer инструкций

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

Реализация

Dockerfile

Таким образом, я изменил команду RUN в моем Dockerfile с

RUN \
    cd /files/tighten-violet && \
    composer --no-ansi --no-interaction install --no-progress  --no-autoloader --no-scripts && \
    composer --no-ansi --no-interaction dump-autoload --no-dev --optimize --classmap-authoritative --no-scripts && \
    composer --no-ansi --no-interaction run-script --no-dev symfony-scripts && \
    php bin/console cache:clear && \
    php bin/console cache:clear --env=prod && \
    php bin/console assetic:dump --env=prod && \
    :

на

RUN \
    cd /files/tighten-violet && \
    composer --no-ansi --no-interaction install --no-progress  --no-autoloader --no-scripts && \
    :

ie: я удалил все, кроме «загрузки пакетов в / vendor ", так как" загрузка "не зависит от переменных среды или конфигурации.

Здесь у меня есть отправляемое docker изображение с уже заполненным /vendor.

Но все еще пропущен один шаг ... где эти пропущенные строки go?

bootstrap. sh

То, что я сделал, это bootstrap скрипт, поэтому я изменил CMD строка из

CMD [ "apachectl", "-D", "FOREGROUND" ]

в

CMD [ "/files/bootstrap.sh" ]

Файл boostrap.sh также копируется в процессе сборки ... и вот содержимое (простая начальная версия):

#!/usr/bin/env bash

# Provision
composer --no-ansi --no-interaction dump-autoload --no-dev --optimize --classmap-authoritative --no-scripts && \
composer --no-ansi --no-interaction run-script --no-dev symfony-scripts
php bin/console cache:clear && \
php bin/console cache:clear --env=prod && \
php bin/console assetic:dump --env=prod

# Start the server
apachectl -D FOREGROUND

Содержит «установочную часть», которая потенциально может зависит от среды, включая дамп автозагрузки, сценарии SensioBundle, а также кэши и дампы. На всякий случай есть ENV-переменные, которые изменяют поведение, которое мы хотим кэшировать.

Это работает на docker run. Но если вы выполните docker stop, а затем docker start снова, часть подготовки также будет запускаться снова и снова (остановка + запуск не останавливает состояние процесса, как это делает «пауза», он убивает процесс и затем перезапускает его снова, начиная с начала bootstrap.sh.

Поэтому я мог бы улучшить сценарий boostrap, чтобы он отмечался, если он был автоматически подготовлен. Это улучшенная (и окончательная) вторая версия bootstrap.sh script:

#!/usr/bin/env bash

provisionIfNeeded()
{
    PROVISIONED=/tmp/provisioned
    if [ ! -f ${PROVISIONED} ]; then

        echo "------------------------------------------------------------------------------"
        echo "Provisioning"
        echo "------------------------------------------------------------------------------"

        composer --no-ansi --no-interaction dump-autoload --no-dev --optimize --classmap-authoritative --no-scripts && \
        composer --no-ansi --no-interaction run-script --no-dev symfony-scripts
        php bin/console cache:clear && \
        php bin/console cache:clear --env=prod && \
        php bin/console assetic:dump --env=prod

        echo "------------------------------------------------------------------------------"
        echo "Ended provisioning"
        echo "------------------------------------------------------------------------------"

        touch ${PROVISIONED}
    fi
}

startServer()
{
    echo "Starting httpd."
    apachectl -D FOREGROUND
}

provisionIfNeeded
startServer

Итак, после docker run:

  1. Сценарий запускается, при необходимости пытается выполнить подготовку.
  2. Он проверяет флаг.
  3. Поскольку он не найден, вызывает ли инициализация недостающие строки в Dockerfile.
  4. В конце инициализации помечает контейнер как подготовленный.
  5. Затем запускается apache.

И после docker start:

  1. Сценарий запускается, пытается выполнить подготовку при необходимости.
  2. Флаг найден , поэтому никакое обеспечение не выполняется.
  3. Затем начинается apache.

10 секунд подготовки отнимаются со стадии сборки и переносятся в стадию запуска.

Минусы

Запуск контейнера только в первый раз длится около На 10 секунд больше, чем если бы мы подготовились на этапе сборки.

Плюсы

Контейнер отлично «записан» с кэшами, которые принадлежат каждой из сред выполнения, сохраняя этап сборки через Dockerfile содержит максимальный общий коэффициент для всех сред.

Надеюсь на помощь!

...