基于Ubuntu 20.04的Dockerfile使用Linux source命令报错如何解决
问题原因及解决方案
错误根因
- 直接原因:Ubuntu 20.04基础镜像默认的
/bin/sh是dash shell,未内置source命令,该命令是bash的专有特性,dash中对应的等效命令为.。 - 隐藏问题:Docker的每一条RUN指令都会启动独立的shell进程,执行完成后进程就会销毁,单条RUN内部加载的环境变量不会持久化到镜像的其他层,也不会在容器启动时生效,即便解决
source报错,后续调用go命令依然会提示找不到。
最优解决方案
直接使用Dockerfile内置的ENV指令全局设置PATH,无需通过profile文件和source操作,环境变量会对镜像所有层、以及后续启动的容器永久生效。同时合并RUN指令减少镜像层数、清理冗余安装包优化镜像体积:
# 先安装必要依赖,避免基础镜像缺少curl的问题 RUN apt update && apt install -y curl && rm -rf /var/lib/apt/lists/* # 合并下载、安装、清理操作,减少镜像层 RUN curl -OL https://golang.org/dl/go1.17.3.linux-amd64.tar.gz \ && tar -C /usr/local -xvf go1.17.3.linux-amd64.tar.gz \ && rm -f go1.17.3.linux-amd64.tar.gz # 全局设置PATH,永久生效 ENV PATH=$PATH:/usr/local/go/bin
其他可选解决方案(不推荐)
如果确实需要通过profile文件配置,可选择以下两种方式解决source报错,但两类方案都无法解决环境变量持久化的问题,后续RUN指令和容器启动时都需要重新加载profile脚本才能正常使用go命令:
方案1:修改默认shell为bash
通过SHELL指令将RUN指令默认使用的shell改为bash,即可正常使用source命令:
SHELL ["/bin/bash", "-c"] # 后续RUN指令默认使用bash执行 RUN source /etc/profile.d/go.sh
方案2:使用POSIX兼容的.命令替代source
将RUN source /etc/profile.d/go.sh替换为以下写法即可兼容dash语法:
RUN . /etc/profile.d/go.sh
内容的提问来源于stack exchange,提问作者Fcoder
相关产品推荐
相关产品推荐

