在Dockerfile

时间:2016-06-20 15:06:15

标签: docker dockerfile

我的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

1 个答案:

答案 0 :(得分:1)

  

<强>更新
  但同样,图像创建时缺少输出,但在我工作时则有效   使用$ docker运行图像--rm -it debian / bin / sh。为什么呢?

这是因为每个语句(通常以大写动词开头,如RUNADDCOPYENV等)都是一个全新的中间容器。

这些中间容器不共享环境(例如环境变量),而是共享联合文件系统。也就是说,只有保存在文件系统中的数据和Dockerfile中定义的变量(例如通过ENV)才能通过中间容器传递。如果您想了解UFS的工作原理,请查看this postUnionFS 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.09.11.1等。