2

Trying to run selenium python on a Docker Apline Linux and getting the "Message: 'chromedriver' executable needs to be in PATH" error because it thinks the file doesn't exist. But tried everything I can fine in other answers, but it still won't launch.

Here's what I tried so far:

  • Added it to folder to PATH and PYTHONPATH.
  • Tried specifying path to chromedriver when I get the driver
  • Tried specifying path to chromium when I get the driver
  • Made sure chromium-browser launches with similar flags
  • chmod +x on chromedriver
  • chmod 777 on chromedriver

See error. in a docker un of image

Update: Adding these packages in Docker file.

RUN apk --update --no-cache add\
  alpine-sdk\
  autoconf\
  automake\
  bash\
  binutils-gold\
  build-base\
  curl\
  dumb-init\
  g++\
  gcc\
  gcompat\
  git\
  gnupg\
  gzip\
  jpeg\
  jpeg-dev\
  libc6-compat\
  libffi\
  libffi-dev\
  libpng\
  libpng-dev\
  libstdc++\
  libtool\
  linux-headers\
  make\
  mysql\
  mysql-client\
  mysql-dev\
  mesa-gles\
  nasm\
  nodejs\
  nss\
  openjdk8-jre\
  openssh-client\
  paxctl\
  python3\
  python3-dev\
  sudo\
  tar\
  unzip\
  wget\
  chromium

And the shell script I'm getting Chromedriver with

#!/bin/bash

LATEST_CHROMEDRIVER=$(curl https://chromedriver.storage.googleapis.com/LATEST_RELEASE)
curl -L https://chromedriver.storage.googleapis.com/$LATEST_CHROMEDRIVER/chromedriver_linux64.zip >> chromedriver.zip
mv -f chromedriver.zip /usr/local/bin/chromedriver.zip
unzip /usr/local/bin/chromedriver.zip -d /usr/local/bin
chmod a+x /usr/local/bin/chromedriver
sudo ln -s /usr/local/bin/chromedriver /usr/bin/chromedriver
rm /usr/local/bin/chromedriver.zip
Cynic
  • 6,779
  • 2
  • 30
  • 49
  • Try removing /usr/local/bin/chromedriver from your PATH. You want directories, not files. Also, even though you have 777 on the file, I would double check you can open() that file from Python. – gzzo Mar 11 '19 at 22:28
  • Good call on path, now set to `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin` but does not fix the problem. `fh = open(chromedriver_path, "r")` can read the file – Cynic Mar 11 '19 at 22:57
  • When you set your `chromedriver_path`, why do you start with the current working directory `os.getcwd(), ...`? I'm not sure what that returns, but I don't know why you can't just set `chromedriver_path = /usr/local/bin/chromedriver` – C. Peck Mar 11 '19 at 23:15
  • I actually started with that. Was kinda trying to combine every answer to similar questions so it doesn't get marked a dupe. But I switched back and it doesn't fix it. – Cynic Mar 11 '19 at 23:19
  • Now that you fixed PATH, does `which chromedriver` return the right file? What happens if you start webdriver.Chrome without specifying an executable path? – gzzo Mar 12 '19 at 15:10
  • `which chromedriver` returns `/usr/local/bin/chromedriver`. I get the same error if I don't specify the path (techincally `No such file or directory: 'chromedriver': 'chromedriver'`). Also tried dropping chromedriver at `/` and in `usr/lib/python3.6/site-packages/`. – Cynic Mar 12 '19 at 18:24
  • Could be ld failure. What is the output of `ldd chromedriver`? – valiano Mar 12 '19 at 19:55
  • Can't post the whole log because it's too long but getting an error. `libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f425d0ac000) Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by usr/local/bin/chromedriver)` `Error relocating usr/local/bin/chromedriver: __sbrk: symbol not found Error relocating usr/local/bin/chromedriver: __res_nclose: symbol not found Error relocating usr/local/bin/chromedriver: __res_ninit: symbol not found Error relocating usr/local/bin/chromedriver: strtoll_l: symbol not found ...` more errors but push character count – Cynic Mar 12 '19 at 20:14
  • Okay, I added what packages I was installing to the body of question. I added libc6-compat and gcompat. Which reduced `ldd` error to: `Error relocating /usr/local/bin/chromedriver: __sbrk: symbol not found [shortning]: __res_nclose: symbol not found [shortning]: __res_ninit: symbol not found [shortning]: strtoll_l: symbol not found [shortning]: strtoull_l: symbol not found [shortning]: __isnan: symbol not found Error relocating /usr/local/bin/chromedriver: backtrace: symbol not found Error relocating /usr/local/bin/chromedriver: __register_atfork: symbol not found` – Cynic Mar 12 '19 at 20:50
  • And now the error I get when trying to run chromedriver is: `ite-packages/selenium/webdriver/common/service.py", line 111, in assert_process_still_running % (self.path, return_code) selenium.common.exceptions.WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 127` – Cynic Mar 12 '19 at 20:51

1 Answers1

3

The output from ldd suggests that chromedriver is built against glibc (GNU standard C library), which isn't compatible to vanilla Alpine, using musl libc.

To fix this, try installing the Alpine compatible version of chromedriver, available in Alpine repositories, using apk add chromium-chromedriver:

https://pkgs.alpinelinux.org/package/v3.9/community/x86_64/chromium-chromedriver

valiano
  • 16,433
  • 7
  • 64
  • 79
  • Thanks for your help. I actually went to apk install and that does work but before i accept the answer. Was wondering if there's a way to install the correct package of glibc on alpine and build against that. Trying something like https://stackoverflow.com/a/37835009/3838981. But still getting an error. Is there a way to tell which glibc the current chromedriver is built against? I've also added the shell script that I'm getting chromedriver with to question just in case. Would prefer to accept something like apk add is easier but still answer original questions how. – Cynic Mar 25 '19 at 18:25
  • @Cynic sure - glad that worked. For installing glibc, follow the steps in this Dockerfile, for example: https://github.com/shaharv/docker/blob/master/alpine/glibc/Dockerfile. It is a custom built glibc linked against musl, by Sasha Gerrand (https://github.com/sgerrand/alpine-pkg-glibc). The steps are basically downloading the glibc apk file, installing it, and running `ldconfig` for updating the dynamic linker. – valiano Mar 25 '19 at 20:06
  • For getting the minimal glibc version required by `chromedriver`, you'll need to dump object symbols and look for `GLIBC` strings, something like: `objdump -T chromedriver | grep GLIBC`. See here: http://www.agardner.me/golang/cgo/c/dependencies/glibc/kernel/linux/2015/12/12/c-dependencies.html – valiano Mar 25 '19 at 20:10
  • Few other notes: 1. Based on the download link it seems that the zip is Linux/mac, which mostly means its linked against glibc - which is the defacto standard libc used in most Linuxes - and indeed not musl libc, used by Alpine. 2. Regarding to `libc6-compat` and `gcompat`: installing them won't do (at least not for complex applications as chromedriver), since they are sort of "adapters" on top of musl, that merely provide glibc interfaces, but not the actual glibc with its issues and quirks. – valiano Mar 25 '19 at 20:16
  • Aw, sorry I edited down the bash script for simplicity and edited out the wrong link. Fixed in question. Will try the rest in a bit when I get time. – Cynic Mar 26 '19 at 15:00
  • @Cynic No worries - without having checked, 99% chance the same applies to this link (a mainland Linux, glibc build and not an Alpine-musl build). It's makes sense to add "Alpine" or "musl" to the zip name, if it's an Alpine build. – valiano Mar 26 '19 at 15:24