【问题标题】:Docker multistage build doesn't recognise installed applicationDocker 多阶段构建无法识别已安装的应用程序
【发布时间】:2018-07-26 21:46:15
【问题描述】:
FROM some-build:latest as build

COPY / /var/www/html

WORKDIR /var/www/html
RUN cd /var/www/html && composer install

FROM some-build2:latest as run

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

ENV PATH ${HOME}/local/bin:${PATH}:/home/site/wwwroot

RUN cd /var/www/html && \
    npm install && \
    npm run production

ENTRYPOINT ["/bin/init_container.sh"]

图像run 包含已安装的npm。尽管如此,npm install 返回错误:/bin/sh: 1: npm: not found

这怎么可能?我做错了什么?


编辑:

作为对@BMitch 评论的回答,当我运行RUN 图像时,容器中的节点位于PATH 上,我可以使用它。路径是/root/local/bin。我已经附上了所有的 Dockerfile。

我有 3 个 docker 文件:
APP
你以前见过的那个。

运行

FROM php:7.2.5-apache
MAINTAINER Azure App Services Container Images <appsvc-images@microsoft.com>

COPY apache2.conf /bin/
COPY init_container.sh /bin/

RUN a2enmod rewrite expires include deflate

# install the PHP extensions we need
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
     libpng-dev \
     libjpeg-dev \
     libpq-dev \
     libldap2-dev \
     libldb-dev \
     libicu-dev \
     libgmp-dev \
     mysql-client \
     libmagickwand-dev \
     openssh-server vim curl wget tcptraceroute \
    && chmod 755 /bin/init_container.sh \
    && echo "root:Docker!" | chpasswd \
    && echo "cd /home" >> /etc/bash.bashrc \
    && ln -s /usr/lib/x86_64-linux-gnu/libldap.so /usr/lib/libldap.so \
    && ln -s /usr/lib/x86_64-linux-gnu/liblber.so /usr/lib/liblber.so \
    && ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h \
    && rm -rf /var/lib/apt/lists/* \
    && pecl install imagick-beta \
    && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \
    && docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd \
    && docker-php-ext-configure mysqli --with-mysqli=mysqlnd \
    && docker-php-ext-install gd \
     mysqli \
     opcache \
     pdo \
     pdo_mysql \
     pdo_pgsql \
     pgsql \
     ldap \
     intl \
     gmp \
     zip \
     bcmath \
     mbstring \
     pcntl \
     xml \
     xmlrpc \
    && docker-php-ext-enable imagick

###################
# Installing node #
###################

RUN apt-get update -yq && apt-get upgrade -yq && \
apt-get install -yq g++ libssl-dev apache2-utils curl git python make nano

# setting up npm for global installation without sudo
# http://stackoverflow.com/a/19379795/580268
RUN MODULES="local" && \
    echo prefix = ~/$MODULES >> ~/.npmrc && \
    echo "export PATH=\$HOME/$MODULES/bin:\$PATH" >> ~/.bashrc && \
    . ~/.bashrc && \
    mkdir ~/$MODULES && \
\
# install Node.js and npm
# https://gist.github.com/isaacs/579814#file-node-and-npm-in-30-seconds-sh
    mkdir ~/node-latest-install && cd $_ && \
    curl http://nodejs.org/dist/v8.11.3/node-v8.11.3.tar.gz | tar xz --strip-components=1 && \
    ./configure --prefix=~/$MODULES && \
    make install && \
    curl -L https://www.npmjs.org/install.sh | sh

# optional, check locations and packages are correct
# RUN which node; node -v; which npm; npm -v; \
#   npm ls -g --depth=0

# Remove unnecessary packages
# RUN apt-get -yq purge g++ libssl-dev curl git python make nano
# RUN apt-get -yq autoremove

###################

RUN   \
   rm -f /var/log/apache2/* \
   && rmdir /var/lock/apache2 \
   && rmdir /var/run/apache2 \
   && rmdir /var/log/apache2 \
   && chmod 777 /var/log \
   && chmod 777 /var/run \
   && chmod 777 /var/lock \
   && chmod 777 /bin/init_container.sh \
   && cp /bin/apache2.conf /etc/apache2/apache2.conf \
   && rm -rf /var/www/html \
   && rm -rf /var/log/apache2 \
   && mkdir -p /home/LogFiles \
   && ln -s /home/LogFiles /var/log/apache2 


RUN { \
        echo 'opcache.memory_consumption=128'; \
        echo 'opcache.interned_strings_buffer=8'; \
        echo 'opcache.max_accelerated_files=4000'; \
        echo 'opcache.revalidate_freq=60'; \
        echo 'opcache.fast_shutdown=1'; \
        echo 'opcache.enable_cli=1'; \
    } > /usr/local/etc/php/conf.d/opcache-recommended.ini

RUN { \
        echo 'error_log=/var/log/apache2/php-error.log'; \
        echo 'display_errors=Off'; \
        echo 'log_errors=On'; \
        echo 'display_startup_errors=Off'; \
        echo 'date.timezone=UTC'; \
    } > /usr/local/etc/php/conf.d/php.ini


COPY sshd_config /etc/ssh/

EXPOSE 2222 8080

ENV APACHE_RUN_USER www-data
ENV PHP_VERSION 7.2.5

ENV PORT 8080
ENV WEBSITE_ROLE_INSTANCE_ID localRoleInstance
ENV WEBSITE_INSTANCE_ID localInstance
ENV PATH ${PATH}:/home/site/wwwroot

ENTRYPOINT ["/bin/init_container.sh"]

构建

FROM composer:latest as composer

FROM php:7.2.5-apache as apache

COPY --from=composer /usr/bin/composer /usr/bin/composer

RUN apt-get update && \
apt-get install git zip unzip -y

编辑 2:
重要的是,如果我删除了RUN npm... 命令,那么整个构建就会成功,并且结果图像包含 npm 并且我可以使用它(我已经通过在交互模式下使用容器进行了验证)。


编辑 3:
这里有很多更简单的解决方案,可以立即试用:

FROM alpine as img1
RUN echo "$HOME" > $HOME/test.txt

FROM alpine as img2
RUN cat $HOME/test.txt

结果是:cat: can't open '/root/test.txt': No such file or directory

【问题讨论】:

  • 可能在 npm install 步骤中尚未安装
  • RUN 映像已经构建,我在交互模式下验证了 npm 已安装并且可以正常工作。所以,到目前为止我所知道的,在那个步骤中应该已经安装了 npm。我刚开始使用 docker,所以也许我遗漏了一些东西。你看到什么了吗?
  • 你能分享一个minimal reproducible example,包括运行图像之类的东西吗?第一个想法是 npm 不在你的路径中。
  • 感谢@BMitch 的评论,我会相应地更新我的问题。
  • @BMitch 我在编辑 3 中添加了我自己的示例,您可以看到一个非常相似的问题,但它要简单得多。

标签: docker dockerfile docker-for-mac docker-multi-stage-build


【解决方案1】:

这里有两个问题。 “php:7.2.5-apache”图像的路径中没有 /root/local/bin,并且您在构建期间没有将其添加到路径中。当您以交互方式登录时,npm 命令将起作用,因为对设置环境的 shell 登录脚本进行了一些更改。在运行任何 npm 命令之前,您需要运行这些环境设置脚本,并且必须在同一个 RUN 命令中完成。要自己验证,您可以检查 .bashrc 中的变量或运行命令以设置 npm 环境。您可以通过将 PATH 值与交互式 shell 和构建中的 env 命令进行比较来验证环境是否不同,如果这是您的问题,您应该会看到两个不同的输出。当我运行你的部分运行图像时,我在 .bashrc 中看到了以下内容:

export PATH=$HOME/local/bin:$PATH

因此,您需要在 Dockerfile 中为运行映像更新该行:

ENV PATH /root/local/bin:${PATH}:/home/site/wwwroot

根据您的编辑 3,这是一个完全不同的问题。您在一个新映像中创建了一个文件,然后返回到该文件不存在的基础映像。如果您想在多阶段构建中查看文件,那么您需要在各个阶段之间复制它,或者使用之前的图像作为您的“来源”。

FROM alpine as img1
RUN echo "$HOME" > $HOME/test.txt

FROM alpine as img2
COPY --from=img1 /root/test.txt /root/test.txt
RUN cat $HOME/test.txt

FROM alpine as img1
RUN echo "$HOME" > $HOME/test.txt

FROM img1 as img2
RUN cat $HOME/test.txt

【讨论】:

  • 好的,让我检查一下。直到,一个小的澄清:我刚开始使用 docker,所以我不确定我是否理解交互式 shell 和我的构建之间的区别。也许这听起来很糟糕,但我认为我可以在我的构建中拥有一个交互式外壳。这意味着我完全错了。你能指出我正确的方向吗?
  • @InfinitePossibilities docker build 不是交互式的。您可以使用交互选项运行任何图像、构建的输出。如果该图像中有一个外壳,您可以交互地运行它。
  • 我当时就是这么想的,但我的印象是所有的图像都有一个外壳。感谢您的澄清。我添加了 ENV(正如您在我的编辑中看到的那样),但结果是一样的。我还验证了 bashrc 文件,但它不包含除此 PATH 设置之外的任何其他内容。
  • @InfinitePossibilities 用env 替换您的npm 命令并比较路径值。一种想法是$HOME 可能未定义,因此也尝试扩展它。
  • 最后,你是对的,我将 npm 更改为 env 并且 PATH 与我使用 ENV 命令设置的不同,也与我在“运行”图像中的不同。为了避免这种情况,我使用绝对路径来运行 npm。在“运行”图像中,npm 位于路径 /root/local/bin。当我为运行映像调用 FROM 时,不应该是同一路径的 npm 吗?
猜你喜欢
  • 2021-07-26
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 2020-04-16
  • 1970-01-01
相关资源
最近更新 更多