Среда разработки PySpark в Docker-контейнере Ubuntu 16.04 - PullRequest
0 голосов
/ 07 мая 2019

Я пытаюсь создать среду разработки, чтобы поиграться с Apache Spark, в частности pyspark, внутри контейнера Docker под управлением Ubuntu 16.04. Для того чтобы поддерживать согласованные среды разработки, когда разные разработчики вносят свой вклад в код, я требую, чтобы вся разработка осуществлялась в четко определенном контейнере Docker.

Моя проблема в том, что я не могу обойти следующую ошибку Java при запуске pyspark исполняемого файла

rmarkbio@linuxkit-025000000001:~/project$ pyspark
Python 3.5.3+ (default, Nov 29 2017, 08:55:08) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
Exception in thread "main" java.lang.ExceptionInInitializerError
    at org.apache.spark.SparkConf$.<init>(SparkConf.scala:716)
    at org.apache.spark.SparkConf$.<clinit>(SparkConf.scala)
    at org.apache.spark.SparkConf.$anonfun$getOption$1(SparkConf.scala:389)
    at scala.Option.orElse(Option.scala:306)
    at org.apache.spark.SparkConf.getOption(SparkConf.scala:389)
    at org.apache.spark.SparkConf.get(SparkConf.scala:251)
    at org.apache.spark.deploy.SparkHadoopUtil$.org$apache$spark$deploy$SparkHadoopUtil$$appendS3AndSparkHadoopConfigurations(SparkHadoopUtil.scala:463)
    at org.apache.spark.deploy.SparkHadoopUtil$.newConfiguration(SparkHadoopUtil.scala:436)
    at org.apache.spark.deploy.SparkSubmit.$anonfun$prepareSubmitEnvironment$3(SparkSubmit.scala:334)
    at scala.Option.getOrElse(Option.scala:138)
    at org.apache.spark.deploy.SparkSubmit.prepareSubmitEnvironment(SparkSubmit.scala:334)
    at org.apache.spark.deploy.SparkSubmit.submit(SparkSubmit.scala:143)
    at org.apache.spark.deploy.SparkSubmit.doSubmit(SparkSubmit.scala:86)
    at org.apache.spark.deploy.SparkSubmit$$anon$2.doSubmit(SparkSubmit.scala:924)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:933)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.net.UnknownHostException: linuxkit-025000000001: linuxkit-025000000001: Name or service not known
    at java.net.InetAddress.getLocalHost(InetAddress.java:1506)
    at org.apache.spark.util.Utils$.findLocalInetAddress(Utils.scala:946)
    at org.apache.spark.util.Utils$.localIpAddress$lzycompute(Utils.scala:939)
    at org.apache.spark.util.Utils$.localIpAddress(Utils.scala:939)
    at org.apache.spark.util.Utils$.$anonfun$localCanonicalHostName$1(Utils.scala:996)
    at scala.Option.getOrElse(Option.scala:138)
    at org.apache.spark.util.Utils$.localCanonicalHostName(Utils.scala:996)
    at org.apache.spark.internal.config.package$.<init>(package.scala:302)
    at org.apache.spark.internal.config.package$.<clinit>(package.scala)
    ... 16 more
Caused by: java.net.UnknownHostException: linuxkit-025000000001: Name or service not known
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:929)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1324)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1501)
    ... 24 more
conn_info_file:  /tmp/tmpiuwhok7q/tmplief2cba
Traceback (most recent call last):
  File "/home/rmarkbio/project/spark-2.4.2-bin-hadoop2.7/python/pyspark/shell.py", line 38, in <module>
    SparkContext._ensure_initialized()
  File "/home/rmarkbio/project/spark-2.4.2-bin-hadoop2.7/python/pyspark/context.py", line 316, in _ensure_initialized
    SparkContext._gateway = gateway or launch_gateway(conf)
  File "/home/rmarkbio/project/spark-2.4.2-bin-hadoop2.7/python/pyspark/java_gateway.py", line 46, in launch_gateway
    return _launch_gateway(conf)
  File "/home/rmarkbio/project/spark-2.4.2-bin-hadoop2.7/python/pyspark/java_gateway.py", line 109, in _launch_gateway
    raise Exception("Java gateway process exited before sending its port number")
Exception: Java gateway process exited before sending its port number
>>> 

Мой Dockerfile определяется как

FROM ubuntu:16.04
ENTRYPOINT [ "/bin/bash", "-l", "-i", "-c" ]

# a few minor docker-specific tweaks
# see https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap
RUN set -xe \
    \
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L40-L48
    && echo '#!/bin/sh' > /usr/sbin/policy-rc.d \
    && echo 'exit 101' >> /usr/sbin/policy-rc.d \
    && chmod +x /usr/sbin/policy-rc.d \
    \
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L54-L56
    && dpkg-divert --local --rename --add /sbin/initctl \
    && cp -a /usr/sbin/policy-rc.d /sbin/initctl \
    && sed -i 's/^exit.*/exit 0/' /sbin/initctl \
    \
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L71-L78
    && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \
    \
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L85-L105
    && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean \
    && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean \
    && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \
    \
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L109-L115
    && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \
    \
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L118-L130
    && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes \
    \
# https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L134-L151
    && echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests

# delete all the apt list files since they're big and get stale quickly
RUN rm -rf /var/lib/apt/lists/*
# this forces "apt-get update" in dependent images, which is also good
# (see also https://bugs.launchpad.net/cloud-images/+bug/1699913)

# enable the universe
RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list

# make systemd-detect-virt return "docker"
# See: https://github.com/systemd/systemd/blob/aa0c34279ee40bce2f9681b496922dedbadfca19/src/basic/virt.c#L434
RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container

# Python installation
RUN apt-get update && apt-get update --fix-missing
RUN apt-get install -y software-properties-common vim
RUN add-apt-repository ppa:jonathonf/python-3.5
RUN apt-get update && export PATH
RUN apt-get install -y build-essential python3.5 python3.5-dev python3-pip python-pip
RUN apt-get update && apt-get install -y git
RUN apt-get update && pip3 install --upgrade pip==19.0.1
RUN pip3 install -U tensorflow
RUN pip3 install -U scikit-learn
RUN apt-get update && pip3 install --no-cache-dir numpy scipy pandas matplotlib
RUN pip3 install neo4j-driver

# NLTK
#RUN pip3 install nltk
#RUN python3 -c "import nltk; nltk.download('stopwords')"
#RUN cp -r /root/nltk_data /usr/share/nltk_data

RUN pip3 install --upgrade pip
RUN pip3 install --upgrade requests==2.13.0
RUN pip3 install --upgrade oauth2client==4.0.0
RUN pip3 install neo4j-driver
RUN echo "Y" | apt-get install curl
RUN apt-get update && apt-get install wget
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get install apt-transport-https
RUN apt-get update
RUN apt-get update && apt-get install -y unixodbc unixodbc-dev tdsodbc python-dev build-essential
RUN apt-get install -y freetds-common freetds-bin freetds-dev

# Spark-related installs
RUN apt-get update && echo "Y" | apt-get install -y openjdk-8-jdk && rm -rf /var/lib/apt/lists/*
RUN apt-get update && echo "Y" | apt-get install scala
RUN wget http://apache.claz.org/spark/spark-2.4.2/spark-2.4.2-bin-hadoop2.7.tgz
RUN tar zxf spark-2.4.2-bin-hadoop2.7.tgz
RUN apt-get update && pip3 install pyspark
RUN apt-get update && pip3 install graphframes


# Set python 3.5 as the default for the container
RUN unlink /usr/bin/python
RUN ln -s /usr/bin/python3.5 /usr/bin/python

RUN apt-get install bc

# Set root password
RUN echo "root:##rmarkbio%%" | chpasswd

# Install sudo
RUN apt-get update && apt-get -y install sudo

# overwrite this with 'CMD []' in a dependent Dockerfile
CMD ["/bin/bash"]

# Create and boot into a development user instead of working as root
RUN groupadd -r username -g 901
RUN useradd -u 901 -r -g username username
RUN echo "username:##username%%" | chpasswd
RUN adduser username sudo
RUN mkdir /home/username
RUN mkdir /home/username/project
RUN mkdir /home/username/logs
RUN chown -R username /home/username
USER username
WORKDIR /home/username/project

Изображение построено с чем-то вроде

docker build -t username/image_name:v000 .

и контейнер с чем-то вроде

        docker run -i -t \
            --entrypoint /bin/bash \
            --net="host" \
            --name=container_name \
            -v $(PWD):/home/username/project \
            -v $(PWD)/../logs:/home/username/logs \
            -v ~/.ssh/id_rsa:/root/.ssh/id_rsa \
            username/image_name:v000

Мне кажется, что я дважды проверил каждую версию Java, scala, Spark и все их соответствующие переменные среды, но я не могу передать эту ошибку в бюджет. Есть только несколько упоминаний об этой ошибке в Интернете, и ни одна из них не помогла. Однако, учитывая, что упоминания об этой ошибке встречаются редко, я думаю, что должно быть что-то простое и очевидное, что я упускаю, потому что многие люди используют эту технологию.

1 Ответ

0 голосов
/ 07 мая 2019

Я нашел источник проблемы, он связан с Docker и как он обрабатывает свое имя хоста в контейнере. У меня также есть неудовлетворительный обходной путь.

Предположим, что я wget отредактировал тарбол Spark и распаковал его

https://www.apache.org/dyn/closer.lua/spark/spark-2.4.2/spark-2.4.2-bin-hadoop2.7.tgz

Зайдя в его каталог, я могу попробовать альтернативный пример сценария, который уже предоставлен

./bin/run-example SparkPi 10

Я продолжаю сталкиваться с этой ошибкой:

rmarkbio@linuxkit-025000000001:~/project/spark-2.4.2-bin-hadoop2.7$ ./bin/run-example SparkPi 10
Exception in thread "main" java.lang.ExceptionInInitializerError
    at org.apache.spark.SparkConf$.<init>(SparkConf.scala:716)
    at org.apache.spark.SparkConf$.<clinit>(SparkConf.scala)
    at org.apache.spark.SparkConf.$anonfun$getOption$1(SparkConf.scala:389)
    at scala.Option.orElse(Option.scala:306)
    at org.apache.spark.SparkConf.getOption(SparkConf.scala:389)
    at org.apache.spark.SparkConf.get(SparkConf.scala:251)
    at org.apache.spark.deploy.SparkHadoopUtil$.org$apache$spark$deploy$SparkHadoopUtil$$appendS3AndSparkHadoopConfigurations(SparkHadoopUtil.scala:463)
    at org.apache.spark.deploy.SparkHadoopUtil$.newConfiguration(SparkHadoopUtil.scala:436)
    at org.apache.spark.deploy.SparkSubmit.$anonfun$prepareSubmitEnvironment$3(SparkSubmit.scala:334)
    at scala.Option.getOrElse(Option.scala:138)
    at org.apache.spark.deploy.SparkSubmit.prepareSubmitEnvironment(SparkSubmit.scala:334)
    at org.apache.spark.deploy.SparkSubmit.submit(SparkSubmit.scala:143)
    at org.apache.spark.deploy.SparkSubmit.doSubmit(SparkSubmit.scala:86)
    at org.apache.spark.deploy.SparkSubmit$$anon$2.doSubmit(SparkSubmit.scala:924)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:933)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.net.UnknownHostException: linuxkit-025000000001: linuxkit-025000000001: Name or service not known
    at java.net.InetAddress.getLocalHost(InetAddress.java:1506)
    at org.apache.spark.util.Utils$.findLocalInetAddress(Utils.scala:946)
    at org.apache.spark.util.Utils$.localIpAddress$lzycompute(Utils.scala:939)
    at org.apache.spark.util.Utils$.localIpAddress(Utils.scala:939)
    at org.apache.spark.util.Utils$.$anonfun$localCanonicalHostName$1(Utils.scala:996)
    at scala.Option.getOrElse(Option.scala:138)
    at org.apache.spark.util.Utils$.localCanonicalHostName(Utils.scala:996)
    at org.apache.spark.internal.config.package$.<init>(package.scala:302)
    at org.apache.spark.internal.config.package$.<clinit>(package.scala)
    ... 16 more
Caused by: java.net.UnknownHostException: linuxkit-025000000001: Name or service not known
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:929)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1324)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1501)
    ... 24 more

Но потом я обнаружил предположение, что часть ошибки гласит

Caused by: java.net.UnknownHostException: linuxkit-025000000001: Name or service not known

означает, что имя хоста, которое здесь "linuxkit-025000000001", не находится в /etc/hosts. Действительно, это так. Я должен зайти в этот файл и изменить

127.0.0.1   localhost

до

127.0.0.1   linuxkit-025000000001    localhost

и это похоже на работу (насколько я могу судить по громоздкому выводу, что я воздержусь от публикации здесь).

Для двойной проверки давайте попробуем запустить pyspark исполняемый файл

rmarkbio@linuxkit-025000000001:~/project/spark-2.4.2-bin-hadoop2.7$ ./bin/pyspark 
Python 3.5.3+ (default, Nov 29 2017, 08:55:08) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
19/05/07 18:49:58 WARN Utils: Your hostname, linuxkit-025000000001 resolves to a loopback address: 127.0.0.1; using 192.168.65.3 instead (on interface eth0)
19/05/07 18:49:58 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address
19/05/07 18:49:58 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 2.4.2
      /_/


Using Python version 3.5.3+ (default, Nov 29 2017 08:55:08)
SparkSession available as 'spark'.

Работает !!!

Итак, какова история linuxkit-025000000001? Это хорошо объясняет

https://github.com/docker/for-mac/issues/2902

Я хочу, чтобы это изменение было в /etc/hosts сразу после создания контейнера из изображения, поэтому мне нужно Dockerfile, чтобы сделать это. К сожалению, это не представляется возможным.

Пока что я не могу найти способ сделать это из Dockerfile; Похоже, что Docker настроен на предотвращение доступа к /etc/hosts до тех пор, пока контейнер не будет создан. Вместо этого я должен согласиться с этим сценарием инициализации, который я вызываю просто init.sh

#!/bin/bash
cp /etc/hosts /home/rmarkbio/project/hosts.new
sed -i "s/127.0.0.1       localhost/127.0.0.1   linuxkit-025000000001    localhost/" /home/rmarkbio/project/hosts.new
echo "somepassword" | sudo -S cp -f /home/rmarkbio/project/hosts.new /etc/hosts
rm /home/rmarkbio/project/hosts.new
echo ''
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...