RUN composer install и npm install в каждой сборке контейнера

Я пытаюсь создать контейнер php-apache с установленными npm и composer и запускаю composer install, npm install в каждой сборке, но получаю ошибки.

# Dockerfile

FROM php:7.4-apache

RUN apt-get -y update && apt-get upgrade -y

RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
        npm \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd

# Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Enable apache modules
RUN a2enmod rewrite headers

EXPOSE 80
#RUN composer install
#RUN npm install

ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]


# docker-compose.yml

version: "3"

services:
  painel-admin:
    build:
      context: ./bin/painel-admin
    container_name: 'painel-admin'
    command: >
      sh -c "php /usr/local/bin/composer install"
    restart: 'always'
    ports:
      - "81:80"
      - "82:443"
    volumes:
      - ${DOCUMENT_ROOT-..}:/var/www/html
      - ${PHP_INI-./config/php/php.ini}:/usr/local/etc/php/php.ini
      - ${VHOSTS_DIR-./config/vhosts}:/etc/apache2/sites-enabled
      - ${LOG_DIR-./logs/apache2}:/var/log/apache2

ошибка журнала:

Действие «-D FOREGROUND sh -c php /usr/local/bin/composer install» завершилось неудачно.

Та же ошибка, если я попытаюсь с npm install.

Я могу запускать команды внутри докера, но я хочу автоматизировать это

Было бы лучше, если бы вы RUN npm install в своем Dockerfile, как вы показываете. Это означало бы COPYвключение кода вашего приложения в образ, а не монтирование его в volumes:. Изменение ENTRYPOINT в изображении на CMD также заставит работать переопределение command:, но это изменит контейнер для запуска команды времени сборки вместо демона HTTP.

David Maze 16.12.2020 03:28

Что вы пытались проверить на причину этой ошибки?

Nico Haase 16.12.2020 13:01
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
5
2
4 450
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете попробовать поставить установку композитора в точку входа.

Я бы обычно использовал файл для этого. Возможно, вы захотите попробовать это.

точка входа.sh

#!/bin/sh
set -e

php /usr/local/bin/composer install

exec "$@"

и в вашем докерфайле

# ...

COPY entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

Что приведет к чему-то вроде этого.

/usr/local/bin/entrypoint.sh /usr/sbin/apache2ctl -D FOREGROUND

Поскольку последняя строка точки входа — exec "$@", она примет все параметры, переданные в entrypoint.sh, и выполнит ее.

Спасибо за ответ Жюльен. Но я думаю, что мне нужно запустить команду в docker-compose.yml, потому что мне нужен том, который я там указал

André Walker 16.12.2020 04:28

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

Julien B. 16.12.2020 04:46
Ответ принят как подходящий

Я думаю, что вы следуете за неправильным подходом. Эти команды являются частью процесса создания образа, поэтому они должны быть частью вашего Dockerfile.

И процесс сборки происходит до того, как тома станут доступны (контейнер не запущен, поэтому от них невозможно зависеть). Что вам нужно сделать, так это скопировать необходимые файлы в образ, который вы создаете, прежде чем запускать composer install.

Более разумным подходом, использующим многоэтапную сборку dockerfiles, будет:

## First stage. Copy project files and run composer
FROM composer:2 as composer_stage

RUN rm -rf /var/www && mkdir -p /var/www/html
WORKDIR /var/www/html

COPY composer.json composer.lock symfony.lock .env ./
COPY public public/

RUN composer install --ignore-platform-reqs --prefer-dist --no-scripts --no-progress --no-suggest --no-interaction --no-dev --no-autoloader

RUN composer dump-autoload --optimize --apcu --no-dev

COPY bin bin/
COPY config config/
COPY src src/

RUN composer run-script $NODEV post-install-cmd; \
    chmod +x bin/console;

## Second stage. Build NPM dependencies

FROM node:12 as npm_builder

COPY --from=composer_stage /var/www/html /var/www/html

WORKDIR /var/www/html
COPY yarn.lock package.json webpack.config.js ./
COPY assets ./assets

RUN yarn install
RUN yarn encore prod

# I'm using yarn here, but using npm would be similar, depending on how your project is setup

# RUN npm install
# RUN npm run build # if necessary and the command exists in your project

## Third stage, mostly copied from your original Dockerfile

FROM php:7.4-apache

RUN apt-get -y update && apt-get upgrade -y

COPY --from=npm_builder /var/www/html /var/www/html

RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
        npm \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd

# Enable apache modules
RUN a2enmod rewrite headers

EXPOSE 80

ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

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

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

Вам нужно будет настроить пути, чтобы они соответствовали желаемой конфигурации (я создаю проект на /var/www/html и указываю веб-серверу на /var/www/html/public, но вы можете легко изменить их).

Поскольку вы используете образ, который включает в себя как веб-сервер, так и среду выполнения PHP, это должно быть так.

Спасибо за ваш ответ @yivi. я использую Ларавель. так что я должен скопировать vendor и node_modules, чтобы избежать повторной установки всех пакетов в каждой сборке?

André Walker 16.12.2020 15:53

Нет, вы копируете только те файлы, которые я показываю в Dockerfile выше. composer.json и composer.lock, а затем package.json и package-lock.json. vendor и node_modules создаются в образе, а не копируются с вашего компьютера.

yivi 16.12.2020 15:58

вы сказали, что указали веб-сервер на /var/www/html/public. Где ты это сделал?

André Walker 16.12.2020 16:01

Это не там. Конфигурация вашего веб-сервера также не включена в ваш вопрос. Где бы вы ни настраивали свой веб-сервер (в вашем случае apache), вы должны указывать на этот каталог.

yivi 16.12.2020 16:08

Другие вопросы по теме