web-dev-qa-db-fra.com

Docker - Exécute la commande après avoir monté un volume

J'ai le fichier Docker suivant pour un runtime php basé sur l'image officielle [php][1].

FROM php:fpm
WORKDIR /var/www/root/
RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libmcrypt-dev \
        libpng12-dev \
        Zip \
        unzip \
    && docker-php-ext-install -j$(nproc) iconv mcrypt \
    && docker-php-ext-configure Gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) Gd \
    && docker-php-ext-install mysqli \
    && docker-php-ext-enable opcache \
    && php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
    && php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
    && php composer-setup.php \
    && php -r "unlink('composer-setup.php');" \
    && mv composer.phar /usr/local/bin/composer

J'ai du mal à exécuter composer install.

Je suppose que le fichier Dockerfile s'exécute avant qu'un volume ne soit monté car je reçois une erreur de fichier composer.json non trouvé si j'ajoutais:

...
&& mv composer.phar /usr/local/bin/composer \
&& composer install

à ce qui précède.

Mais, en ajoutant la propriété suivante à docker-compose.yml:

command: sh -c "composer install && composer require drush/drush"

semble mettre fin au conteneur une fois l'exécution de la commande terminée.

Y a-t-il un moyen de:

  • attendre qu'un volume soit monté
  • lancez composer install en utilisant le fichier composer.json monté
  • avoir le conteneur continuer à courir après

?

7
Raphael Rafatpanah

Je suis généralement d'accord avec la réponse de Chris au développement local. Je vais proposer quelque chose qui se combine avec une fonctionnalité récente de Docker qui pourrait permettre de développer à la fois le développement local et le déploiement éventuel de la production avec la même image.

Commençons d'abord par l'image que nous pouvons créer de manière à pouvoir être utilisée pour le développement local ou le déploiement, quelque part contenant le code et les dépendances. La dernière version de Docker (17.05) propose une nouvelle fonctionnalité de construction en plusieurs étapes. Dans ce cas, nous pouvons d'abord installer toutes vos dépendances Composer dans un dossier du contexte de construction, puis les copier ultérieurement dans l'image finale sans avoir à ajouter Composer à l'image finale. Cela pourrait ressembler à:

FROM composer as composer
COPY . /app
RUN composer install --ignore-platform-reqs --no-scripts

FROM php:fpm
WORKDIR /var/www/root/
RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libmcrypt-dev \
        libpng12-dev \
        Zip \
        unzip \
    && docker-php-ext-install -j$(nproc) iconv mcrypt \
    && docker-php-ext-configure Gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) Gd \
    && docker-php-ext-install mysqli \
    && docker-php-ext-enable opcache
COPY . /var/www/root
COPY --from=composer /app/vendor /var/www/root/vendor

Cela supprime tout Composer de l'image d'application elle-même et utilise plutôt la première étape pour installer les dépendances dans un autre contexte et les copier dans l'image finale.

Au cours du développement, vous avez quelques options. Selon votre commande docker-compose.yml, il semblerait que vous montiez l'application dans le conteneur en tant que .:/var/www/root. Vous pouvez ajouter un service composer à votre docker-compose.yml, semblable à mon exemple, à l’emplacement https://Gist.github.com/andyshinn/e2c428f2cd234b718239 . Ici, vous ne faites que docker-compose run --rm composer install lorsque vous devez mettre à jour des dépendances localement (cela conserve la construction des dépendances à l'intérieur du conteneur, ce qui peut être important pour les extensions natives compilées, en particulier si vous déployez en tant que conteneurs et développez sous Windows ou Mac).

L'autre option consiste simplement à faire quelque chose de similaire à ce que Chris a déjà suggéré, et à utiliser l'image officielle de Composer pour mettre à jour et gérer les dépendances en cas de besoin. J'ai déjà fait quelque chose comme cela localement où j'avais des dépendances privées sur GitHub qui nécessitaient une authentification SSH:

docker run --rm --interactive --tty --volume $PWD:/app:rw,cached --volume $SSH_AUTH_SOCK:/ssh-auth.sock --env SSH_AUTH_SOCK=/ssh-auth.sock --volume $COMPOSER_HOME:/composer composer:1.4 install --ignore-platform-reqs --no-scripts

Pour récapituler, le raisonnement de cette méthode de construction de l'image et d'installation de dépendances Composer à l'aide d'un conteneur/service externe:

  • Les dépendances spécifiques à la plate-forme seront construites correctement pour le conteneur (architecture Linux vs Windows ou Mac).
  • Aucun compositeur ou PHP n'est requis sur votre ordinateur local (tout est contenu dans Docker et Docker Compose).
  • L'image initiale que vous avez créée est exécutable et déployable sans qu'il soit nécessaire d'y monter du code. En développement, vous remplacez simplement le dossier /var/www/root par un volume local.
5
Andy Shinn

Cela fait 5 heures que je suis dans ce trou de lapin, toutes les solutions sont bien trop compliquées. La solution la plus simple consiste à exclure les modules vendeur ou node_modules et répertoires similaires du volume .

#docker-compose.yml
volumes:
      - .:/srv/app/
      - /srv/app/vendor/

Cela va donc mapper le répertoire du projet en cours mais exclure son sous-répertoire vendor. N'oubliez pas la barre oblique finale!

Alors maintenant, vous pouvez facilement exécuter l’installation du composeur dans dockerfile et lorsque docker monte votre volume, il ignore le répertoire du fournisseur.

1
Buksy

S'il s'agit d'un environnement de développement général, l'intention n'est pas vraiment idéale car elle relie l'application à la configuration de Docker.

Lancez simplement composer install séparément par un autre moyen (une image est disponible pour cela sur dockerhub, ce qui vous permet juste de faire (docker run -it --rm -v $(pwd):/app composer/composer install).


Mais oui, il est possible que vous ayez besoin de la dernière ligne de la Dockerfile pour être bash -c "composer install && php-fpm".


  • attendre qu'un volume soit monté

Non, les volumes ne peuvent pas être montés pendant un processus de génération de menu fixe. Bien que vous puissiez copier le code source dans.

  • lancez composer composer en utilisant le fichier monté composer.json

Non, voir la réponse ci-dessus.

  • avoir le conteneur continuer à courir après

Oui, vous devrez exécuter php-fpm --nodaemonize (qui est un processus long, par conséquent, il ne se terminera pas.

1
Chris Stryczynski