Docker - 安装卷后执行命令

时间:2017-07-01 19:53:16

标签: docker docker-compose dockerfile

我有一个基于官方[php][1]图像的php运行时的以下Dockerfile。

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

我无法运行composer install

我猜测Dockerfile在挂载卷之前运行,因为如果添加以下内容我收到composer.json文件未找到错误:

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

以上。

但是,将以下属性添加到docker-compose.yml

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

似乎在命令完成执行后终止容器。

有办法:

  • 等待卷安装
  • 使用已安装的composer install文件
  • 运行composer.json
  • 让容器继续运行

4 个答案:

答案 0 :(得分:5)

我普遍同意克里斯对当地发展的回答。我将提供一些与最近的Docker功能相结合的东西,它可以为同一图像设置本地开发和最终生产部署的路径。

让我们首先从可以用于包含代码和依赖项的本地开发或部署的方式构建的映像开始。在最新的Docker版本(17.05)中,我们可以利用新的多阶段构建功能。在这种情况下,我们可以首先将所有Composer依赖项安装到构建上下文中的文件夹,然后将它们复制到最终映像,而无需将Composer添加到最终映像。这可能看起来像:

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

这将从应用程序映像本身中删除所有Composer,而是使用第一个阶段在另一个上下文中安装依赖项,并将它们复制到最终映像。

现在,在开发过程中你有一些选择。根据您的docker-compose.yml命令,您可能会将应用程序作为.:/var/www/root安装到容器中。您可以向composer添加docker-compose.yml服务,类似于我在https://gist.github.com/andyshinn/e2c428f2cd234b718239的示例。在这里,当您需要在本地更新依赖项时,您只需执行docker-compose run --rm composer install(这样可以在容器内部构建依赖项,这对于本机编译的扩展非常重要,特别是如果您要部署为容器并在Windows或Mac上进行开发)。 / p>

另一个选择是执行类似于Chris已经建议的操作,并使用官方的Composer镜像在需要时更新和管理依赖项。我之前在本地做了类似的事情,之前我在GitHub上有私有依赖,需要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

回顾一下,使用外部容器/服务构建映像和安装Composer依赖项的方法的原因是:

  • 将为容器正确构建特定于平台的依赖项(Linux体系结构与Windows或Mac)。
  • 本地计算机上不需要Composer或PHP(它全部包含在Docker和Docker Compose中)。
  • 您构建的初始映像是可运行且可部署的,无需将代码装入其中。在开发过程中,您只是覆盖了具有本地卷的/var/www/root文件夹。

答案 1 :(得分:1)

如果这是针对一般开发环境的,那么意图并不理想,因为它将应用程序与Docker配置耦合。

只需通过其他方式单独运行composer install(在dockerhub上有可用的图像,这样您就可以(docker run -it --rm -v $(pwd):/app composer/composer install)。

但是,您可能需要Dockerfile中的最后一行为bash -c "composer install && php-fpm"

  • 等待卷安装

不,在docker构建过程中无法装入卷。虽然您可以复制源代码。

  • 使用已安装的composer.json文件运行composer install

不,见上述回复。

  • 让容器继续运行

是的,您需要执行php-fpm --nodaemonize(这是一个长时间运行的进程,因此它不会终止。

答案 2 :(得分:1)

我在这个兔子洞里呆了5个小时,那里的所有解决方案都太复杂了。最简单的解决方案是exclude vendor or node_modules and similar directories from volume

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

因此,这将映射当前项目目录,但不包括其供应商子目录。不要忘记斜杠!

因此,现在您可以轻松地在dockerfile中运行composer install,当docker装载您的卷时,它将忽略供应商目录。

答案 3 :(得分:0)

在将卷装入Docker容器后执行命令

假设您正在从公共存储库中获取依赖项

docker run --interactive -t --privileged --volume ${pwd}:/xyz composer /bin/sh -c 'composer install'

要从私有git存储库中获取依赖项,您需要复制/创建ssh密钥,我想这应该不在这个问题的范围之内。