├── Dockerfile ├── README.md ├── docker-compose.yml ├── entrypoint.sh └── mount └── script.py /Dockerfile: -------------------------------------------------------------------------------- 1 | # Base is Ubuntu 22.04 2 | FROM debian:bullseye 3 | 4 | # VNC server port 5 | EXPOSE 5900 6 | 7 | # set the timezone so that tzdata doesn't ask for it 8 | ENV DEBIAN_FRONTEND=noninteractive 9 | # ENV TZ=Europe/Berlin 10 | # RUN ln -fs /usr/share/zoneinfo/Europe/Berlin /etc/localtime 11 | 12 | 13 | # Install dependencies 14 | RUN apt-get update && apt-get install -y \ 15 | python3 \ 16 | python3-venv \ 17 | python3-pip \ 18 | xvfb \ 19 | fluxbox \ 20 | x11vnc \ 21 | x11-apps \ 22 | sudo \ 23 | wget \ 24 | curl \ 25 | htop 26 | 27 | # Create a new virtual environment 28 | RUN python3 -m venv /opt/venv 29 | 30 | # Activate the virtual environment 31 | ENV PATH="/opt/venv/bin:$PATH" 32 | 33 | # Install Python dependencies and update pip 34 | RUN pip install --upgrade pip 35 | RUN pip install ipython 36 | RUN pip install undetected-chromedriver 37 | 38 | # add google chrome repo and accept the key + install chrome 39 | RUN echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list 40 | RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-chrome.gpg 41 | RUN apt-get update && apt-get install google-chrome-stable=112.* -y 42 | 43 | # Copy the entrypoint.sh to the container into the root directory 44 | COPY entrypoint.sh /entrypoint.sh 45 | 46 | # Make the entrypoint script executable 47 | RUN chmod +x /entrypoint.sh 48 | 49 | # Set the entrypoint 50 | ENTRYPOINT ["/entrypoint.sh"] 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # An example Dockerfile for undedected-chromedriver 2 | 3 | This Dockerfile builds an image with undetected-chromedriver and a VNC server. 4 | The entrypoint ensures that the VNC server is running before the script is executed. 5 | To execute your script you should mount the `mount` directory into the containers `/opt/wd` 6 | directory. 7 | 8 | Example command to build and run the container: 9 | ```bash 10 | docker build -t undetected-chromedriver . && docker run -it --rm --volume ./mount:/opt/wd --name undetected-chromedriver -e VNC_PASSWORD=123456 -p 5900:5900 undetected-chromedriver python script.py 11 | ``` 12 | The VNC server is now accessible on localhost:5900 with password 123456 13 | You could also use the docker-compose.yml file. 14 | 15 | ## If you don't see the Browser: 16 | The chrome window will be closed if your script ends. 17 | Also don't use `input()` to stop your script from stopping because if you run 18 | the script in a non-interactive shell it will not be able to open the input 19 | stream which results in an error and termination of the script. 20 | You could use `while True: sleep(10)` to keep the script running. 21 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | undetected-chromedriver: 4 | build: . 5 | image: undetected-chromedriver 6 | container_name: undetected-chromedriver 7 | command: python script.py 8 | entrypoint: /entrypoint.sh 9 | volumes: 10 | - ./mount:/opt/wd 11 | ports: 12 | - "5900:5900" 13 | environment: 14 | - VNC_PASSWORD=123456 15 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export DISPLAY=:0 4 | rm -f /tmp/.X0-lock # from not cleanly stopping the container 5 | 6 | echo -e "\n### Starting Xvfb..." 7 | Xvfb -ac -screen 0 1920x1080x24 & 8 | 9 | echo -e "\n### Starting fluxbox..." 10 | fluxbox -screen 0 &> /dev/null & 11 | 12 | echo -e "\n### Starting x11vnc..." 13 | x11vnc -passwd ${VNC_PASSWORD:-password} -N -forever -rfbport 5900 &> /dev/null & 14 | 15 | cd /opt/wd 16 | 17 | echo -e "\n### done with entrypoint.sh handing over to cmd" 18 | echo -e "\n### pwd: $(pwd)" 19 | echo -e "\n### cmd: $@" 20 | "$@" 21 | 22 | echo -e "\n### cmd finished, holding container open (till x is closed)" 23 | wait # waits for all background processes to finish (join) 24 | -------------------------------------------------------------------------------- /mount/script.py: -------------------------------------------------------------------------------- 1 | import undetected_chromedriver as uc 2 | from selenium.webdriver.remote.webdriver import By 3 | import selenium.webdriver.support.expected_conditions as EC 4 | from selenium.webdriver.support.wait import WebDriverWait 5 | 6 | import time 7 | 8 | print("start of script") 9 | 10 | options = uc.ChromeOptions() 11 | driver = uc.Chrome(options) 12 | driver.maximize_window() 13 | 14 | # open google 15 | driver.get("https://www.google.com") 16 | 17 | # accept cookies if necessary 18 | driver.find_elements(By.XPATH, '//*[contains(text(), "Alle ablehnen")]')[-1].click() 19 | 20 | # find input field 21 | try: 22 | inp_search = driver.find_element(By.XPATH, '//textarea[@name="q"]') 23 | except: 24 | inp_search = driver.find_element(By.XPATH, '//input[@name="q"]') 25 | 26 | time.sleep(0.5) # <- thats bad practice (google needs some time to have the 27 | # handler ready for the input) 28 | 29 | # search for rickroll 30 | inp_search.send_keys("rickroll\n") 31 | 32 | # don't stop the script so chrome doesn't close and we can see the result 33 | while True: time.sleep(10) 34 | --------------------------------------------------------------------------------