{"id":9061,"date":"2018-05-11T07:17:57","date_gmt":"2018-05-11T11:17:57","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=9061"},"modified":"2018-05-21T05:01:05","modified_gmt":"2018-05-21T09:01:05","slug":"building-your-own-docker-images-for-different-browser-versions","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/building-your-own-docker-images-for-different-browser-versions\/","title":{"rendered":"Building your own docker images for different browser versions"},"content":{"rendered":"<p>When any application is deployed the software needs to be tested across multiple platforms and different versions of browsers. It&#8217;s tough to maintain environments with different versions of browsers. One approach is to use cloud solutions like <a href=\"https:\/\/saucelabs.com\/\">Sauce Labs<\/a> or <a href=\"https:\/\/www.browserstack.com\/\">BrowserStack <\/a>which provides multi-version-browser support. But in case if you want to build your own environment which is easy to control and maintain, you can create your own docker images\/containers for different browser versions as and when you need.<\/p>\n<hr\/>\n<h3>Overview<\/h3>\n<p>This post assumes you already know a little about <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> and <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile<\/a>. In the following sections we will be talking about below items:<\/p>\n<ul>\n1. Third party sources for getting archived versions of browsers<br \/>\n2. Why we chose to create Docker images\/containers for different versions of browsers?<br \/>\n3. Creating a Dockerfile<br \/>\n4. Building your own images using this Dockerfile<br \/>\n5. Creating a container and running Selenium tests\n<\/ul>\n<hr\/>\n<h4>1.Third party sources for getting archived versions of browsers<\/h4>\n<p>We started exploring, where to get the official downloads of older stable browser(Chrome\/Firefox) versions for Windows, Linux and Mac. Unlike Mozilla, Google seems to keep very quiet about versions, it does not keep an archive version so the old versions are gone forever as soon as a newer version becomes available. There is no official way to download Google Chrome older versions. So, we will have to rely on third-party sources for getting archived versions. There are some decent third party sites providing old versions. One such site is <a href=\"http:\/\/www.slimjet.com\/chrome\/google-chrome-old-version.php\">Slimjet<\/a>. You can get older versions of Chrome using Slimjet. They have cached old versions of Chrome for Windows, Linux and Mac. Just run the executable and extract the files to any folder on your hard drive.<\/p>\n<hr\/>\n<h4>2. Why we chose to create Docker images\/containers for different versions of browsers?<\/h4>\n<p>We can&#8217;t (easily) maintain multiple versions of the same browser in a single system. So the best way to tackle this to create different <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> images\/containers for different browser versions and run your scripts in each container. In the following sections, we will be briefing you about how we created different containers for different browser versions and how we ran our Python-Selenium tests. We have created a <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile<\/a> and build different images using this Dockerfile for different versions of Chrome and Firefox. A Dockerfile is a text document that contains all the commands a user could execute on the command line to assemble an image. Whoever wants to test their application on for eg., Chrome version 57 can simply pull this image from <a href=\"https:\/\/hub.docker.com\/\">DockerHub<\/a> and create a container and run their scripts. <\/p>\n<hr\/>\n<h4>3. Creating a Dockerfile<\/h4>\n<p>To give an overview of our Dockerfile, we created two different Dockerfiles for Chrome and Firefox respectively. It contains below steps. You may also refer to our other post on <a href=\"https:\/\/qxf2.com\/blog\/preparing-a-docker-image-for-running-selenium-tests\/\">Preparing a docker image<\/a> on Docker file creation and running selenium tests.<\/p>\n<li><strong>Step 1<\/strong> is basic step where we pull the base image Ubuntu(We used Ubuntu 16.04.) <\/li>\n<li><strong>Step 2<\/strong> is installation of Xvfb display and other essentials<\/li>\n<li><strong>Step 3<\/strong> is setup browser version and driver using ARG parameters. The ARG instruction defines a variable that users can pass at build-time with the docker build command. You can specify versions by using CHROME_VERSION and FIREFOX_VERSION in <em>&#8211;build-arg<\/em> variables. Since we decided to use the old versions of Chrome\/Firefox this step is critical. To know more about using ARG variables refer <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#using-arg-variables\">here<\/a><\/li>\n<li><strong>Step 4<\/strong> is installing Python 2.7 and Python Pip<\/li>\n<p><strong><em>Dockerfile<\/em><\/strong> for Chrome browser<\/p>\n<pre lang=\"python\">\r\n#Step 1\r\n#Dockerfile to build an image for different versions of chrome\r\n#Pull ubuntu 16.04 base image\r\nFROM ubuntu\r\nMAINTAINER Qxf2 Services\r\n\r\n#Step 2\r\n#Essential tools and xvfb\r\nRUN apt-get update && apt-get install -y \\\r\n    software-properties-common \\\r\n    unzip \\\r\n    curl \\\r\n    wget \\\r\n    xvfb\r\n\r\n#Step 3\r\n#Chrome browser to run the tests\r\nARG CHROME_VERSION=65.0.3325.181\r\nRUN curl https:\/\/dl-ssl.google.com\/linux\/linux_signing_key.pub | apt-key add \\\r\n      && wget https:\/\/www.slimjet.com\/chrome\/download-chrome.php?file=lnx%2Fchrome64_$CHROME_VERSION.deb \\\r\n      && dpkg -i download-chrome*.deb || true\r\nRUN apt-get install -y -f \\\r\n      && rm -rf \/var\/lib\/apt\/lists\/*\r\n\r\n#Disable the SUID sandbox so that chrome can launch without being in a privileged container\r\nRUN dpkg-divert --add --rename --divert \/opt\/google\/chrome\/google-chrome.real \/opt\/google\/chrome\/google-chrome \\\r\n        && echo \"#! \/bin\/bash\\nexec \/opt\/google\/chrome\/google-chrome.real --no-sandbox --disable-setuid-sandbox \\\"\\$@\\\"\" > \/opt\/google\/chrome\/google-chrome \\\r\n        && chmod 755 \/opt\/google\/chrome\/google-chrome\r\n\r\n#Chrome Driver\r\nARG CHROME_DRIVER_VERSION=2.37\r\nRUN mkdir -p \/opt\/selenium \\\r\n        && curl http:\/\/chromedriver.storage.googleapis.com\/$CHROME_DRIVER_VERSION\/chromedriver_linux64.zip -o \/opt\/selenium\/chromedriver_linux64.zip \\\r\n        && cd \/opt\/selenium; unzip \/opt\/selenium\/chromedriver_linux64.zip; rm -rf chromedriver_linux64.zip; ln -fs \/opt\/selenium\/chromedriver \/usr\/local\/bin\/chromedriver;\r\n\r\n#Firefox browser to run the tests\r\nRUN apt-get update && apt-get install -y firefox\r\n\r\n#Geckodriver\r\nENV GECKODRIVER_VERSION 0.16.0\r\nRUN wget --no-verbose -O \/tmp\/geckodriver.tar.gz https:\/\/github.com\/mozilla\/geckodriver\/releases\/download\/v$GECKODRIVER_VERSION\/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz \\\r\n  && rm -rf \/opt\/geckodriver \\\r\n  && tar -C \/opt -zxf \/tmp\/geckodriver.tar.gz \\\r\n  && rm \/tmp\/geckodriver.tar.gz \\\r\n  && mv \/opt\/geckodriver \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && chmod 755 \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && ln -fs \/opt\/geckodriver-$GECKODRIVER_VERSION \/usr\/bin\/geckodriver \\\r\n  && ln -fs \/opt\/geckodriver-$GECKODRIVER_VERSION \/usr\/bin\/wires\r\n\r\n#Step 4\r\n#Python 2.7 and Python Pip\r\nRUN apt-get update\r\nRUN apt-get install -y \\\r\n    python \\\r\n    python-setuptools \\\r\n    python-pip\r\n<\/pre>\n<p>In the above Dockerfile, if you look at Step 3 we are downloading and installing the <em>.deb<\/em> file for the specified chrome version and chrome driver version from <a href=\"http:\/\/www.slimjet.com\/chrome\/google-chrome-old-version.php\">Slimjet<\/a> website using ARG variables.<\/p>\n<p><em><strong>#Dockerfile<\/strong><\/em> for Firefox browser<\/p>\n<pre lang=\"python\">\r\n#Step 1\r\n#Dockerfile to build an image for different versions of firefox\r\n#Pull ubuntu 16.04 base image\r\nFROM ubuntu\r\nMAINTAINER Qxf2 Services\r\n\r\n#Step 2\r\n#Essential tools and xvfb\r\nRUN apt-get update && apt-get install -y \\\r\n    software-properties-common \\\r\n    unzip \\\r\n    curl \\\r\n    wget \\\r\n    bzip2\\\r\n    xvfb\r\n\r\n#Step 3\r\n#Firefox\r\nARG FIREFOX_VERSION=59.0.2\r\nRUN apt-get update -qqy \\\r\n  && apt-get -qqy --no-install-recommends install firefox \\\r\n  && rm -rf \/var\/lib\/apt\/lists\/* \/var\/cache\/apt\/* \\\r\n  && wget --no-verbose -O \/tmp\/firefox.tar.bz2 https:\/\/download-installer.cdn.mozilla.net\/pub\/firefox\/releases\/$FIREFOX_VERSION\/linux-x86_64\/en-US\/firefox-$FIREFOX_VERSION.tar.bz2 \\\r\n  && apt-get -y purge firefox \\\r\n  && rm -rf \/opt\/firefox \\\r\n  && tar -C \/opt -xjf \/tmp\/firefox.tar.bz2 \\\r\n  && rm \/tmp\/firefox.tar.bz2 \\\r\n  && mv \/opt\/firefox \/opt\/firefox-$FIREFOX_VERSION \\\r\n  && ln -fs \/opt\/firefox-$FIREFOX_VERSION\/firefox \/usr\/bin\/firefox\\\r\n  \r\n#GeckoDriver\r\nARG GECKODRIVER_VERSION=0.20.1\r\nRUN wget --no-verbose -O \/tmp\/geckodriver.tar.gz https:\/\/github.com\/mozilla\/geckodriver\/releases\/download\/v$GECKODRIVER_VERSION\/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz \\\r\n  && rm -rf \/opt\/geckodriver \\\r\n  && tar -C \/opt -zxf \/tmp\/geckodriver.tar.gz \\\r\n  && rm \/tmp\/geckodriver.tar.gz \\\r\n  && mv \/opt\/geckodriver \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && chmod 755 \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && ln -fs \/opt\/geckodriver-$GECKODRIVER_VERSION \/usr\/bin\/geckodriver\r\n\r\n#Step 4\r\n#Python 2.7 and Python Pip\r\nRUN apt-get update\r\nRUN apt-get install -y \\\r\n    python \\\r\n    python-setuptools \\\r\n    python-pip\r\n<\/pre>\n<p>Since Mozilla maintains archived versions, for installing older firefox version we simply defined the ARG variables for FIREFOX_VERSION and GECKODRIVER_VERSION in the Dockerfile and downloaded the Firefox binaries.<\/p>\n<hr\/>\n<h4>4. Building your own images using these Dockerfiles<\/h4>\n<p>You can either build your own image using above Dockerfiles or you can directly download the image from our <a href=\"https:\/\/hub.docker.com\/r\/qxf2rohand\">Docker Hub repository<\/a>. If you want more finely tuned specification you can build your own images by using <em>&#8211;build-args<\/em> arguments when building the Docker image. The build uses the Dockerfile which needs to be saved in any directory in your system. We have a created few images <em>python-selenium-chrome<\/em>(for Chrome) and <em>python-selenium-firefox<\/em>(for Firefox) with different tags(Tag name specifies the version number) for different versions and pushed into our Dockerhub <a href=\"https:\/\/hub.docker.com\/u\/qxf2rohand\/\">link<\/a><\/p>\n<p>Here is the sample command we used to build an image for chrome 57 version with compatible driver 2.28<\/p>\n<p><em><strong>#build the python-selenium-chrome with a specific chrome driver and chrome version.<\/strong><\/em><\/p>\n<pre lang=\"python\">\r\n$ docker build -t python-selenium-chrome:chrome57 --build-arg CHROME_DRIVER_VERSION=2.28 --build-arg CHROME_VERSION=57.0.2987.133 -f Dockerfile .\r\n<\/pre>\n<p><em><strong>#build the python-selenium-firefox with specific firefox version<\/strong><\/em><\/p>\n<pre lang=\"python\">\r\n$ docker build -t python-selenium-firefox:firefox52 --build-arg FIREFOX_VERSION=52.0.1 -f Dockerfile .\r\n<\/pre>\n<p>NOTE: Sometimes you may run into situations where the ChromeDriver version you are using is NOT compatible with the Chrome version you are using. If you run into these issues, please cross check and specify the correct driver version.<\/p>\n<hr\/>\n<h4>5. Creating a container and running Selenium tests<\/h4>\n<p>The images that we created are capable of running any Python-based Selenium tests. To run the Selenium tests using this image, you need to go through following steps:<\/p>\n<p>i) Create a Docker container out of this image and enter into the container using the following commands:<\/p>\n<pre lang=\"python\">\r\ndocker run -it qxf2rohand\/python-selenium-chrome:chrome57 \"\/bin\/bash\"\r\n<\/pre>\n<p>Export display and enable Xvfb using following 2 commands:<\/p>\n<pre lang=\"python\">\r\nexport DISPLAY=:20\r\nXvfb :20 -screen 0 1366x768x16 &\r\n<\/pre>\n<p>Install Selenium using pip<\/p>\n<pre lang=\"python\">\r\npip install selenium\r\n<\/pre>\n<p>ii) Use any Linux editor you like and add your test inside the container. You can also use the sample Selenium code (selenium_sample.py) given below. This selenium test visits Qxf2 Services website and prints the title.<\/p>\n<pre lang=\"python\">\r\n# contents of selenium_sample.py\r\nfrom selenium import webdriver\r\n \r\ndriver = webdriver.Chrome()\r\ndriver.get(\"http:\/\/www.qxf2.com\")\r\nprint driver.title\r\ndriver.quit()\r\n<\/pre>\n<p>iii) Run the selenium test using the following command:<\/p>\n<pre lang=\"python\">\r\npython selenium_sample.py\r\n<\/pre>\n<p>The output will be similar to the screenshot shown below.<\/p>\n<figure id=\"attachment_9160\" aria-describedby=\"caption-attachment-9160\" style=\"width: 389px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/04\/chrome57_version.jpg\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/04\/chrome57_version.jpg\" alt=\"\" width=\"389\" height=\"49\" class=\"size-full wp-image-9160\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/04\/chrome57_version.jpg 389w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/04\/chrome57_version-300x38.jpg 300w\" sizes=\"auto, (max-width: 389px) 100vw, 389px\" \/><\/a><figcaption id=\"caption-attachment-9160\" class=\"wp-caption-text\">Output of selenium_sample.py<\/figcaption><\/figure>\n<hr\/>\n<p>We hope this post is helpful to get started with building your own images with specific versions and finely tuned configurations and run your scripts on any version of browsers you want.<\/p>\n<p>This article was produced by Qxf2 Services. <strong>Learn more <a href=\"https:\/\/qxf2.com\/blog\/about-qxf2\/\">about Qxf2 Services<\/a>.<\/strong><\/p>\n<hr\/>\n<h3>References<\/h3>\n<p>1) <a href=\"https:\/\/stackoverflow.com\/questions\/40938190\/create-docker-image-to-run-selenium-tests-on-different-browser-versions\">Create docker image to run selenium tests on different browser versions<\/a><\/p>\n<p>2) <a href=\"https:\/\/stackoverflow.com\/questions\/41180704\/dockerfile-and-dpkg-command\">dpkg command and installation<\/a><\/p>\n<p>3) <a href=\"https:\/\/github.com\/SeleniumHQ\/docker-selenium\/wiki\/Building-your-own-images\">Building your own images<\/a><\/p>\n<hr\/>\n","protected":false},"excerpt":{"rendered":"<p>When any application is deployed the software needs to be tested across multiple platforms and different versions of browsers. It&#8217;s tough to maintain environments with different versions of browsers. One approach is to use cloud solutions like Sauce Labs or BrowserStack which provides multi-version-browser support. But in case if you want to build your own environment which is easy to [&hellip;]<\/p>\n","protected":false},"author":16,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38,136,140,168,167,120,30],"tags":[],"class_list":["post-9061","post","type-post","status-publish","format-standard","hentry","category-automation","category-chrome","category-docker","category-drivers","category-firefox","category-geckodriver","category-selenium"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/9061","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=9061"}],"version-history":[{"count":82,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/9061\/revisions"}],"predecessor-version":[{"id":9361,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/9061\/revisions\/9361"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=9061"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=9061"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=9061"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}