Dockerfile中使用shell表达式的默认值(ARG和ENV)

10

我希望您能将版本号作为单个参数,并在Dockerfile中的RUN脚本中提取URL的主要/次要数字。

ARG CUDA_VERSION
ARG CUDNN_VERSION

ENV CUDA_FULL="${CUDA_VERSION:-8.0.61_375.26}" \
    CUDA_MAJOR="$(echo ${CUDA_VERSION:-8.0.61_375.26} | cut -d. -f1)" \
    CUDA_MINOR="$(echo ${CUDA_VERSION:-8.0.61_375.26} | cut -d. -f2)" \
    CUDA_MAJMIN="$CUDA_MAJOR.$CUDA_MINOR"
ENV CUDNN_FULL="${CUDNN_VERSION:-7.0.1}" \
    CUDNN_MAJOR="$(echo ${CUDNN_VERSION:-7.0.1} | cut -d. -f1)" \
    CUDNN_MINOR="$(echo ${CUDNN_VERSION:-7.0.1} | cut -d. -f2)" \
    CUDNN_MAJMIN="$CUDNN_MAJOR.$CUDNN_MINOR"

RUN curl -LO https://.../${CUDNN_FULL}/.../...${CUDA_MAJMIN}...

如果我尝试上述方法,那么shell表达式将不会被评估,只是作为后续的RUN脚本原样粘贴。是否有更好的方法来实现这一点,而不需要创建一个包装此Dockerfile的外部shell脚本?

2
我无法相信还没有一个优雅的解决方案来解决那个问题。 - Tobbey
1个回答

14

根据文档:

${variable_name}语法也支持一些标准的bash修改符,如下所示:

${variable:-word}表示如果变量已设置,则结果将是该值。如果未设置该变量,则结果为word。

${variable:+word}表示如果变量已设置,则结果为word,否则结果为空字符串。

ENV是特殊的Docker构建命令,不支持这个功能。你要找的是在ENV中运行Shell命令。所以这样做行不通。

可能的解决方案是使用bash脚本

cuda_version.sh

#!/bin/bash
CUDA_FULL="${CUDA_VERSION:-8.0.61_375.26}"
CUDA_MAJOR="$(echo ${CUDA_VERSION:-8.0.61_375.26} | cut -d. -f1)"
CUDA_MINOR="$(echo ${CUDA_VERSION:-8.0.61_375.26} | cut -d. -f2)"
CUDA_MAJMIN="$CUDA_MAJOR.$CUDA_MINOR" 
CUDNN_FULL="${CUDNN_VERSION:-7.0.1}"
CUDNN_MAJOR="$(echo ${CUDNN_VERSION:-7.0.1} | cut -d. -f1)"
CUDNN_MINOR="$(echo ${CUDNN_VERSION:-7.0.1} | cut -d. -f2)"
CUDNN_MAJMIN="$CUDNN_MAJOR.$CUDNN_MINOR"

把你的 Dockerfile 改为:

ARG CUDA_VERSION=8.0.61_375.26
ARG CUDNN_VERSION=7.0.1

ENV CUDA_VERSION=${CUDA_VERSION} CUDNN_VERSION=${CUDNN_VERSION}
COPY cuda_version.sh /cuda_version.sh
RUN bash -c "source /cuda_version.sh && curl -LO https://.../${CUDNN_FULL}/.../...${CUDA_MAJMIN}..."
您可以从您的 shell 文件中删除默认值,因为它们始终存在于 Dockerfile 的参数/环境变量中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接