首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从Dockerfile CMD调用sh文件时,无法在docker容器中设置环境变量

从Dockerfile CMD调用sh文件时,无法在docker容器中设置环境变量
EN

Stack Overflow用户
提问于 2021-08-16 11:34:09
回答 1查看 904关注 0票数 0

我将按照链接创建一个星火集群。我能够运行星星团。但是,我必须给出一个启动spark-shell的绝对路径。我正在尝试在start-shell.sh中设置环境变量,即PATH和其他几个变量。然而,它并没有在容器中设置那个。我尝试使用容器内的printenv打印它。但这些变量从未得到反映。

我是否试图不正确地设置环境变量?不过,星火群集正在成功运行。

我正在使用dockerCompose.yml来构建和重新创建一个图像和容器。

船坞-拼装-建造

Dockerfile

代码语言:javascript
运行
复制
# builder step used to download and configure spark environment
FROM openjdk:11.0.11-jre-slim-buster as builder

# Add Dependencies for PySpark
RUN apt-get update && apt-get install -y curl vim wget software-properties-common ssh net-tools ca-certificates python3 python3-pip python3-numpy python3-matplotlib python3-scipy python3-pandas python3-simpy

# JDBC driver download and install
ADD https://go.microsoft.com/fwlink/?linkid=2168494 /usr/share/java

RUN update-alternatives --install "/usr/bin/python" "python" "$(which python3)" 1

# Fix the value of PYTHONHASHSEED
# Note: this is needed when you use Python 3.3 or greater
ENV SPARK_VERSION=3.1.2 \
HADOOP_VERSION=3.2 \
SPARK_HOME=/opt/spark \
PYTHONHASHSEED=1

# Download and uncompress spark from the apache archive
RUN wget --no-verbose -O apache-spark.tgz "https://archive.apache.org/dist/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz" \
&& mkdir -p ${SPARK_HOME} \
&& tar -xf apache-spark.tgz -C ${SPARK_HOME} --strip-components=1 \
&& rm apache-spark.tgz

我的码头-火花

在Dockerfile中使用ENV环境下的SPARK_BIN="${SPARK_HOME}/bin/时,环境变量得到设置。通过使用printenv,可以在码头容器中看到它。

代码语言:javascript
运行
复制
FROM apache-spark

WORKDIR ${SPARK_HOME}

ENV SPARK_MASTER_PORT=7077 \
SPARK_MASTER_WEBUI_PORT=8080 \
SPARK_LOG_DIR=${SPARK_HOME}/logs \
SPARK_MASTER_LOG=${SPARK_HOME}/logs/spark-master.out \
SPARK_WORKER_LOG=${SPARK_HOME}/logs/spark-worker.out \
SPARK_WORKER_WEBUI_PORT=8080 \
SPARK_MASTER="spark://spark-master:7077" \
SPARK_WORKLOAD="master"        

COPY start-spark.sh /

CMD ["/bin/bash", "/start-spark.sh"]

start-spark.sh

代码语言:javascript
运行
复制
#!/bin/bash
. "$SPARK_HOME/bin/load-spark-env.sh"

export SPARK_BIN="${SPARK_HOME}/bin/" # This doesn't work here
export PATH="${SPARK_HOME}/bin/:${PATH}" # This doesn't work here      

# When the spark work_load is master run class org.apache.spark.deploy.master.Master
if [ "$SPARK_WORKLOAD" == "master" ];
then

export SPARK_MASTER_HOST=`hostname`           # This works here

cd $SPARK_BIN && ./spark-class org.apache.spark.deploy.master.Master --ip $SPARK_MASTER_HOST --port $SPARK_MASTER_PORT --webui-port $SPARK_MASTER_WEBUI_PORT >> $SPARK_MASTER_LOG. 

我的文件结构是

  • 码头文件
  • 这使用由dockerfile创建的预先构建的映像。
  • start-spark.sh #调用了购买dockerfile火花
  • uses #使用build参数来构建来自dockerfile的映像。

从主容器内部

代码语言:javascript
运行
复制
root@3abbd4508121:/opt/spark# export
declare -x HADOOP_VERSION="3.2"
declare -x HOME="/root"
declare -x HOSTNAME="3abbd4508121"
declare -x JAVA_HOME="/usr/local/openjdk-11"
declare -x JAVA_VERSION="11.0.11+9"
declare -x LANG="C.UTF-8"
declare -x OLDPWD
declare -x PATH="/usr/local/openjdk-11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/opt/spark"
declare -x PYTHONHASHSEED="1"
declare -x SHLVL="1"
declare -x SPARK_HOME="/opt/spark"
declare -x SPARK_LOCAL_IP="spark-master"
declare -x SPARK_LOG_DIR="/opt/spark/logs"
declare -x SPARK_MASTER="spark://spark-master:7077"
declare -x SPARK_MASTER_LOG="/opt/spark/logs/spark-master.out"
declare -x SPARK_MASTER_PORT="7077"
declare -x SPARK_MASTER_WEBUI_PORT="8080"
declare -x SPARK_VERSION="3.1.2"
declare -x SPARK_WORKER_LOG="/opt/spark/logs/spark-worker.out"
declare -x SPARK_WORKER_WEBUI_PORT="8080"
declare -x SPARK_WORKLOAD="master"
declare -x TERM="xterm"
root@3abbd4508121:/opt/spark# 
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-16 14:09:50

在Docker中有几种不同的设置环境变量的方法,还有几种运行进程的不同方法。容器通常运行一个进程,该进程由图像的ENTRYPOINTCMD设置控制。如果在容器中docker exec第二个进程,该进程不会作为主进程的子进程运行,也不会看到由该主进程设置的环境变量。

在这里显示的设置中,start-spark.sh脚本是主容器进程(它是图像的CMD)。如果您使用docker exec your-container printenv,它将看到在Dockerfile中设置的内容,而不会看到在这个脚本中设置的内容。

像文件系统路径这样的东西通常在每次运行容器时都会被修复,不管您在那里运行什么命令,所以您可以在Dockerfile中指定这些

代码语言:javascript
运行
复制
ENV SPARK_BIN=${SPARK_HOME}/bin PATH=${SPARK_BIN}:${PATH}

您可以在您的Dockerfile中同时指定一个ENTRYPOINT和一个CMD;如果您指定了,那么CMD将作为参数传递给ENTRYPOINT。这导致了一种有用的模式,其中CMD是一个标准的shell命令,而ENTRYPOINT是一个包装器,它执行第一次设置,然后运行它。您可以将脚本分成两部分:

代码语言:javascript
运行
复制
#!/bin/sh
# spark-env.sh
. "${SPARK_BIN}/load-spark-env.snh"
exec "$@"
代码语言:javascript
运行
复制
#!/bin/sh
# start-spark.sh
spark-class org.apache.spark.deploy.master.Master \
  --ip "$SPARK_MASTER_HOST" \
  --port "$SPARK_MASTER_PORT" \
  --webui-port "$SPARK_MASTER_WEBUI_PORT"

然后在Dockerfile中指定这两个部分

代码语言:javascript
运行
复制
COPY spark-env.sh start-spark.sh /
ENTRYPOINT ["/spark-env.sh"] # must be JSON-array syntax
CMD ["/start-spark.sh"] # or any other valid CMD

这对于您的调试非常有用,因为在docker rundocker-compose run指令中覆盖ENTRYPOINT是很简单的,而ENTRYPOINT则是现成的。

代码语言:javascript
运行
复制
docker-compose run spark \
  printenv

这将根据所有相同的Dockerfile设置启动一个新容器。当它运行时,它运行的是printenv而不是映像中的CMD。这将在ENTRYPOINT脚本中执行第一次设置,然后最终的exec "$@"行将运行printenv,而不是启动Spark应用程序。这将向您展示应用程序启动时的环境。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68802116

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档