Docker 多阶段构建无法识别已安装的应用程序
Docker multistage build doesn't recognise installed application
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
return 错误:/bin/sh: 1: npm: not found
这怎么可能?我做错了什么?
编辑:
作为对@BMitch 评论的回答,当我 运行 RUN
图像时,在容器中节点位于 PATH 上,我可以使用它。路径是/root/local/bin
。我已经附上了所有的 Dockerfiles。
我有 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
#
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
这里有两个问题。 "php:7.2.5-apache" 图像在路径中不会有 /root/local/bin,并且您在构建期间没有将它添加到路径中。由于对设置环境的 shell 登录脚本进行了一些更改,npm 命令将在您以交互方式登录时起作用。在 运行 任何 npm
命令之前,您需要 运行 这些环境设置脚本,并且必须在同一个 运行 命令中完成。要自己验证,您可以检查 .bashrc 中的变量或命令 运行 设置 npm 环境。您可以通过在交互式 shell 和构建中将 PATH 值与 env
命令进行比较来验证环境是否不同,如果这是您的问题,您应该会看到两个不同的输出。当我 运行 你的 运行 图像的一部分时,我在 .bashrc 中看到以下内容:
export PATH=$HOME/local/bin:$PATH
因此,您需要为 运行 图像更新 Dockerfile 中的行:
ENV PATH /root/local/bin:${PATH}:/home/site/wwwroot
根据您的编辑 3,这是一个完全不同的问题。您在一个新映像中创建了一个文件,然后返回到该文件不存在的基础映像。如果您想在多阶段构建中查看该文件,那么您需要在各个阶段之间复制它,或者使用之前的图像作为您的 "from".
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
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
return 错误:/bin/sh: 1: npm: not found
这怎么可能?我做错了什么?
编辑:
作为对@BMitch 评论的回答,当我 运行 RUN
图像时,在容器中节点位于 PATH 上,我可以使用它。路径是/root/local/bin
。我已经附上了所有的 Dockerfiles。
我有 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
#
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
这里有两个问题。 "php:7.2.5-apache" 图像在路径中不会有 /root/local/bin,并且您在构建期间没有将它添加到路径中。由于对设置环境的 shell 登录脚本进行了一些更改,npm 命令将在您以交互方式登录时起作用。在 运行 任何 npm
命令之前,您需要 运行 这些环境设置脚本,并且必须在同一个 运行 命令中完成。要自己验证,您可以检查 .bashrc 中的变量或命令 运行 设置 npm 环境。您可以通过在交互式 shell 和构建中将 PATH 值与 env
命令进行比较来验证环境是否不同,如果这是您的问题,您应该会看到两个不同的输出。当我 运行 你的 运行 图像的一部分时,我在 .bashrc 中看到以下内容:
export PATH=$HOME/local/bin:$PATH
因此,您需要为 运行 图像更新 Dockerfile 中的行:
ENV PATH /root/local/bin:${PATH}:/home/site/wwwroot
根据您的编辑 3,这是一个完全不同的问题。您在一个新映像中创建了一个文件,然后返回到该文件不存在的基础映像。如果您想在多阶段构建中查看该文件,那么您需要在各个阶段之间复制它,或者使用之前的图像作为您的 "from".
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