我的Dockerfile中有以下命令:
RUN echo "\
export NODE_VERSION=$(\
curl -sL https://nodejs.org/dist/latest/ |\
tac |\
tac |\
grep -oPa -m 1 '(?<=node-v)(.*?)(?=-linux-x64\.tar\.xz)' |\
head -1\
)" >> /etc/bash.bashrc
RUN source /etc/bash.bashrc
以下命令应将export NODE_VERSION=6.2.2
存储在/etc/bash.bashrc
中,但它不存储任何内容。
但是当我使用bash在图像中并手动输入以下命令时,这是有效的。
更新
我将shell从bash
更改为Debian / Ubuntu默认dash
,这是POSIX标准。我删除了这一行:
RUN ln -sf /bin/bash /bin/sh && ln -sf /bin/bash /bin/sh.distrib
我尝试使用export
添加到环境变量中:
RUN export NODE_VERSION=$(\
curl -sL https://nodejs.org/dist/latest/ |\
tac |\
tac |\
grep -oPa -m 1 '(?<=node-v)(.*?)(?=-linux-x64\.tar\.xz)' |\
head -1\
)
但同样,在创建图像时输出丢失,但在使用$ docker run --rm -it debian /bin/sh
运行图像时有效。为什么呢?
更新2:
看起来最终解决方案应该是这样的:
RUN NODE_VERSION=$( \
curl -sL https://nodejs.org/dist/latest/ | \
tac | \
tac | \
grep -oPa -m 1 '(?<=node-v)(.*?)(?=-linux-x64\.tar\.xz)' | \
head -1 \
) && echo $NODE_VERSION
ENV NODE_VERSION $NODE_VERSION
echo $NODE_VERSION
在执行Dockerfile时应该返回6.2.2
,但ENV NODE_VERSION $NODE_VERSION
无法读取此内容。有没有办法全局定义变量或如何将RUN
的输出传递给ENV
?
解决方案:
我最终将node.js安装部分放在相同的RUN
命令下:
RUN NODE_VERSION=$( \
curl -sL https://nodejs.org/dist/latest/ | \
tac | \
tac | \
grep -oPa -m 1 '(?<=node-v)(.*?)(?=-linux-x64\.tar\.xz)' | \
head -1 \
) \
&& echo $NODE_VERSION \
&& curl -SLO "https://nodejs.org/dist/latest/node-v$NODE_VERSION-linux-x64.tar.xz" -o "node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/latest/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt
答案 0 :(得分:1)
<强>更新强>
但同样,图像创建时缺少输出,但在我工作时则有效 使用$ docker运行图像--rm -it debian / bin / sh。为什么呢?
这是因为每个语句(通常以大写动词开头,如RUN
,ADD
,COPY
,ENV
等)都是一个全新的中间容器。
这些中间容器不共享环境(例如环境变量),而是共享联合文件系统。也就是说,只有保存在文件系统中的数据和Dockerfile中定义的变量(例如通过ENV
)才能通过中间容器传递。如果您想了解UFS的工作原理,请查看this post和UnionFS Wiki。
如果您的目标是在每次构建映像时安装最新节点。试试nvm
(节点版本管理器)怎么样?
ARG UBUNTU=16.04
# Pull base image.
FROM ubuntu:${UBUNTU}
# arguments
ARG NVM=0.33.9
ARG NODE=node
# update apt
RUN apt-get update
# Install curl
RUN apt-get install -y curl
# Set home for NVM
ENV NVM_DIR=/home/inazuma/.nvm
# Install Node.js with NVM
RUN mkdir -p ${NVM_DIR} && \
curl -o- https://raw.githubusercontent.com/creationix/nvm/v${NVM}/install.sh | bash && \
. ${NVM_DIR}/nvm.sh && \
nvm install ${NODE}
# The first following line should always be called in each intermediate container
# to gain nvm, node and npm command
. ${NVM_DIR}/nvm.sh && nvm use ${NODE} && \
npm install -g cowsay && \
cowsay "Making Docker images is really a headache!"
# Set up your PATH for nvm, node and npm command
CMD ". ${NVM_DIR}/nvm.sh && nvm use ${NODE} && bash"
请注意,nvm
不会跨中间容器保留,因此您应该使用. ${NVM_DIR}/nvm.sh
为每个新的中间容器设置nvm
命令。
NVM在本地管理节点二进制,使用nvm use ${NODE}
将节点和npm包含在PATH中。在NVM中,node
代表最新版本Node的别名;因此,我们将NODE
参数设置为node
(它也可以设置为一个语义版本字符串,如5.0
,9.11.1
等。