This reference covers version: latest

Selenoid is a powerful Golang implementation of original Selenium hub code. It is using Docker to launch browsers. Please refer to GitHub repository if you need source code.

1. Getting Started

1.1. Quick Start Guide

1.1.1. Start Selenoid

  1. Make sure you have recent Docker version installed.

  2. Download Configuration Manager (Selenoid quick installation binary) for your platform from releases page.

  3. On Linux or Mac give execution permissions to binary:

    $ chmod +x cm
  4. Run one command to start Selenoid:

    $ ./cm selenoid start --vnc

    Running this command with sudo can lead to broken installation. Recommended way is running Selenoid as regular user. On Linux to have permissions to access Docker you may need to add your user to docker group:

    $ sudo usermod -aG docker $USER
  5. Optionally run one more command to start Selenoid UI:

    $ ./cm selenoid-ui start

1.1.2. Run Your Tests

  1. Run your tests against Selenoid like you do with regular Selenium hub:

    Tests Endpoint
    http://localhost:4444/wd/hub

    If something does not work, you can easily check that Selenoid is running with opening status url:

    Current Selenoid Status
    http://localhost:4444/status

    A successful request should return a JSON with browser usage statistics.

  2. To open Selenoid UI navigate to the following page in your browser:

    UI Default URL
    http://localhost:8080/

1.2. Starting Selenoid Manually

  1. This guide shows how to start Selenoid manually. When in doubt take a look at Configuration Manager first.

  2. This guide assumes you already know how to deal with command line and know basic Docker commands.

1.2.1. Prepare Configuration

  1. Create config/browsers.json configuration file with content:

    config/browsers.json
    {
        "firefox": {
            "default": "57.0",
            "versions": {
                "57.0": {
                    "image": "selenoid/firefox:88.0",
                    "port": "4444",
                    "path": "/wd/hub"
                }
            }
        }
    }
    For Chrome and Opera images "path" is "/" instead of "/wd/hub"
  2. Pull browser Docker image:

    $ docker pull selenoid/firefox:88.0.

1.2.2. Browser Images

We maintain a set of prebuilt Docker container images for different browsers including:

All these images are free to use. See image tags for a list of supported versions. Build files are stored in selenoid-images repository. Feel free to create issues or request images for new versions.

  1. Complete list of browser images can be found in Browser Image information

  2. These images support all UTF-8 locales. This can be important if you want to save files using national alphabet symbols. You can enable your preferred locale in browsers configuration file by setting respective environment variables:

{
    "chrome": {
        "default": "64.0",
        "versions": {
            "64.0": {
                "image": "selenoid/chrome:90.0",
                //...
                "env" : ["LANG=ru_RU.UTF-8", "LANGUAGE=ru:en", "LC_ALL=ru_RU.UTF-8"]
            }
        }
    }
}

1.2.3. Start Selenoid

Option 1: start Selenoid binary
  1. Download binary for your operating system from releases page and save it as selenoid (or selenoid.exe on windows).

    Add execution permission in case of *nix os-type with chmod +x selenoid.
  2. Then run:

    *nix
    ./selenoid
    Windows
    selenoid.exe
  3. It should write to console something like:

    2017/11/26 21:23:43 Loading configuration files...
    2017/11/26 21:23:43 Loaded configuration from [config/browsers.json]
    
    ...
    
    2017/11/26 21:23:43 Listening on :4444
Option 2: start Selenoid container

If you have Docker installed you can omit downloading binary and run it inside container. Prepare config, pull browser image, then run:

*nix
docker run -d                                   \
--name selenoid                                 \
-p 4444:4444                                    \
-v /var/run/docker.sock:/var/run/docker.sock    \
-v /your/directory/config/:/etc/selenoid/:ro              \
aerokube/selenoid:latest-release
Windows PowerShell
> $current = $PWD -replace "\\", "/" -replace "C", "c"  (1)
> docker run -d                                         `
--name selenoid                                         `
-p 4444:4444                                            `
-v //var/run/docker.sock:/var/run/docker.sock           `
-v ${current}/config/:/etc/selenoid/:ro                 `
aerokube/selenoid:latest-release
1 Simple macros to get $PWD with compatible form assumed your directory located on C: drive

1.2.4. Selenoid under Windows

While we normally recommend to start Selenoid using Configuration Manager on any platform, it is possible to start it under Windows manually.

Most of the differences are related to Docker, so please refer to Docker documentation on any errors first.

The main difference from Unix operating systems is how volumes are mounted. In any Windows paths back slashes (\) should be replaced by forward slashes (/) and drive letter should be lower cased. Also start with forward slash and remove colon.

Example 1. Mount directory

C:\Users\admin becomes /c/Users/admin

Another story with docker.sock, which should be mounted as -v //var/run/docker.sock:/var/run/docker.sock (note two forward slashes at the beginning)

So assuming that configuration file is located at C:\Users\admin\selenoid a typical startup command can look like:

docker run -d --name selenoid                   `
-p 4444:4444                                    `
-v //var/run/docker.sock:/var/run/docker.sock   `
-v /c/Users/admin/selenoid:/etc/selenoid:ro                 `
aerokube/selenoid:latest-release

You can use simple Powershell macros to automatically get correct $PWD value (assumed you are on C:):

> $current = $PWD -replace "\\", "/" -replace "C", "c"

1.3. Frequently Asked Questions

1.3.1. Selenoid in Kubernetes

We are very frequently asked whether it is possible to run Selenoid in Kubernetes cluster. The answer is - it is possible but we do not recommend doing this:

  1. Selenoid can only work directly with Docker API and was created to be run on a workstation or a virtual machine with Docker installed.

  2. Kubernetes contrarily has a completely different API and can be using Docker as a container runtime backend. In some clusters rkt is used instead of Docker and in that case Selenoid will not work.

  3. Even if Selenoid works - all browser containers will be started on the same Kubernetes node where it is running.

  4. So far as Selenoid is using Docker API directly - Kubernetes will not be aware of additional containers started by Selenoid. This is dangerous and can potentially lead to overloaded Kubernetes nodes.

  5. You can only have one Selenoid replica maximum. This is because Selenoid internally stores a list of running sessions in memory.

If you need Selenium in Kubernetes or Openshift, we have a separate solution called Moon.

1.3.2. Logs and Dirs

Where are Selenoid logs?

Selenoid outputs its logs to stdout. Selenoid launched as a binary should output logs to the screen. To see Selenoid logs launched as Docker container type:

$ docker logs selenoid

To follow the logs add one more flag:

$ docker logs -f selenoid

Where are recorded videos stored?

Default location when installed with cm is ~/.aerokube/selenoid/video or C:\Users\<user>\.aerokube\selenoid\video.

1.3.3. Limits and Timeouts

How can I limit overall browsers consumption?

You have to use -limit flag to specify total number of parallel sessions. Default value is 5. See Resources Consumption section on how to determine total number of parallel sessions.

Can I limit per-version browser consumption?

No, this is not supported. We consider the only reasonable limitation should be the overall browsers consumption. This is important to not overload the hardware.

How can I adjust Selenoid timeouts?

The main timeout flag is -timeout, specified as 60s or 2m or 1h. It means maximum amount of time between subsequent HTTP requests to Selenium API. When there are no requests during this time period - session is automatically closed. Selenoid also has more subtle timeouts like:

  • -service-startup-timeout - container or driver process startup timeout

  • -session-attempt-timeout - new session HTTP request timeout, applied when container or driver has started

  • -session-delete-timeout - container or process removal timeout, applied after driver.quit() call

1.3.4. Resources Consumption

How many resources browser containers consume?

This depends on your tests. We recommend to start with 1 CPU and 1 Gb of memory per container as a rough estimate and then increase -limit checking that your tests work stably.

Do VNC and non-VNC browser images memory and CPU consumption differ?

The only difference between these images - is a running VNC server (x11vnc) consuming approximately 20 Megabytes of RAM in idle state which is negligible compared to browser memory consumption.

1.3.5. Features not Working

Selenoid does not start: open config/browsers.json: no such file or directory

This usually happens when Selenoid is started in Docker container with custom command-line arguments, e.g.:

$ docker run <some-args> aerokube/selenoid:some-version -limit 10

In that case you have to specify path to configuration file explicitly (cm tool does this automatically):

$ docker run <some-args> aerokube/selenoid:some-version -limit 10 -conf /etc/selenoid/browsers.json

Getting error: create container: Error response from daemon: client version 1.36 is too new

You have to run Selenoid binary \ container with DOCKER_API_VERSION variable specifying your Docker API version. cm tool does this automatically for you. To determine API version type:

$ docker version | grep API

Then run Selenoid like the following:

$ DOCKER_API_VERSION=1.32 ./selenoid <rest-of-args> # As a binary
$ docker run -e DOCKER_API_VERSION=1.32 <rest-of-args> aerokube/selenoid:some-version # As Docker container

Video feature not working

When running Selenoid as Docker container video feature can be not working (because of misconfiguration). If your video files are named like selenoid607667f7e1c7923779e35506b040300d.mp4 and you are seeing the following log message…​

2018/03/20 21:06:37 [9] [VIDEO_ERROR] [Failed to rename /video/selenoid607667f7e1c7923779e35506b040300d.mp4 to /video/8019c4bc-9bec-4a8b-aa40-68d1db0cffd2.mp4: rename /video/selenoid607667f7e1c7923779e35506b040300d.mp4 /video/8019c4bc-9bec-4a8b-aa40-68d1db0cffd2.mp4: no such file or directory]

... then check that:

  1. You are passing an OVERRIDE_VIDEO_OUTPUT_DIR environment variable pointing to a directory on the host machine where video files are actually stored

  2. When passing custom arguments to Selenoid container (such as -limit or -timeout) you also have to pass -video-output-dir /opt/selenoid/video and mount host machine video dir to /opt/selenoid/video

Can’t get VNC feature to work: Disconnected

Please check that you have enableVNC = true capability in your tests

Seeing black screen with a cross in VNC window

You are using driver.close() instead of driver.quit() and just closed the last browser tab instead of removing the session.

Can Selenoid pull browser images automatically?

No, we did not implement this feature intentionally. We consider that all such cluster maintenance tasks can influence performance and stability when done automatically.

Is it possible to run Selenoid in Docker macvlan network?

Yes, this is possible. See the following Github issue for possible solutions.

2. Main Features

2.1. Video Recording

  1. This feature only works when browsers are run in containers.

  2. Video can be recorded with both vnc or non-vnc browser images.

  3. An additional enableVideo capability should be added to tests. See Special Capabilities section for more details.

Selenoid can capture browser screen and save it to MPEG-4 video file using H264 codec. Video recording works by attaching a separate container with video capturing software to running browser container.

To use this feature you should:

  1. Pull video recorder image once:

    $ docker pull selenoid/video-recorder:latest-release
  2. When running Selenoid in Docker container:

    1. Mount a directory from the host machine (e.g. ~/.aerokube/selenoid/video) to store video files to /opt/selenoid/video.

    2. Pass an additional OVERRIDE_VIDEO_OUTPUT_DIR environment variable with absolute path to video directory on host machine. This is required because video recorder container, automatically created by Selenoid should save video to host machine video storage directory.

  3. When running Selenoid as a binary - videos will be stored in video directory inside current working directory.

    Example Docker Command
    $ docker run -d                                 \
    --name selenoid                                 \
    -p 4444:4444                                    \
    -v /var/run/docker.sock:/var/run/docker.sock    \
    -v /your/directory/config/:/etc/selenoid/:ro              \
    -v /your/directory/video/:/opt/selenoid/video/            \
    -e OVERRIDE_VIDEO_OUTPUT_DIR=/your/directory/video/       \
    aerokube/selenoid:latest-release
All these actions are automatically done when starting Selenoid via Configuration Manager selenoid start command.

2.1.1. On Windows

With absolute path your command will look like:

Windows PowerShell
> docker volume create selenoid-videos
> $current = $PWD -replace "\\", "/" -replace "C", "c"    (1)
> docker run -d                                         `
--name selenoid                                         `
-p 4444:4444                                            `
-v //var/run/docker.sock:/var/run/docker.sock           `
-v ${current}/config/:/etc/selenoid/:ro                 `
-v /c/selenoid/video/:/opt/selenoid/video/              ` (2)
-e OVERRIDE_VIDEO_OUTPUT_DIR=/c/selenoid/video/         ` (3)
aerokube/selenoid:latest-release
1 Simple macros to get $PWD with compatible form assumed your directory located on C: drive
2 Should be absolute path in compatible form
3 Should be same as in (2)

2.1.2. Downloading Video Files from Selenoid

You can access recorded video files using the following URL:

Direct Link to File
http://selenoid-host.example.com:4444/video/<filename>.mp4
Direct link will work only after session has finished because Selenoid renames temporary filename to <session-id>.mp4 (by default) at the session close.

To see all available files use:

Listing All Video Files
http://selenoid-host.example.com:4444/video/

2.1.3. Deleting Video Files

Selenoid intentionally has no built-in logic to automatically remove old video files. To limit storage space consumption you have two alternatives:

  1. Schedule scripts automatically removing files older than desired date and time. An example command under Unix operating systems can look like:

    Shell Command to Remove Old Video Files
    $ find /path/to/video/dir -mindepth 1 -maxdepth 1 -mmin +120 -name '*.mp4' | xargs rm -rf

    Notice -mmin +120 argument meaning to only process files older than 2 hours (120 minutes).

  2. Send video removal requests (e.g. from passed test cases). Just use DELETE HTTP method and Selenoid video URL:

    Deleting Video File via HTTP API
    $ curl -X DELETE http://selenoid-host.example.com:4444/video/<filename>.mp4

2.2. Saving Session Logs

An additional enableLog capability should be added to tests. See Special Capabilities section for more details.

Selenoid can save log files for every running session to a separate file. By default log files are saved as <session-id>.log but you can alter file name via logName capability.

To enable this feature you only need to add -log-output-dir </path/to/some/dir> flag to Selenoid:

$ ./selenoid -log-output-dir /path/to/some/dir

When running Selenoid in Docker container - don’t forget to mount logs directory from the host machine:

Example Docker Command
$ docker run -d
--name selenoid                                 \
-p 4444:4444                                    \
-v /var/run/docker.sock:/var/run/docker.sock    \
-v /your/directory/config/:/etc/selenoid/:ro              \
-v /your/directory/logs/:/opt/selenoid/logs/              \
aerokube/selenoid:latest-release -log-output-dir /opt/selenoid/logs
This feature is automatically enabled when starting Selenoid via Configuration Manager selenoid start command.

2.2.1. Downloading Log Files from Selenoid

You can access saved log files using the following URL:

Direct Link to Log File
http://selenoid-host.example.com:4444/logs/<filename>.log
Direct link will work only after session has finished because Selenoid renames temporary filename to <session-id>.log (by default) at the session close.

To see all available files use:

Listing All Log Files
http://selenoid-host.example.com:4444/logs/

2.2.2. Deleting Log Files

Similarly to video files it’s up to you when to delete old log files. Either remove log files from the directory using a scheduled job or send log removal requests:

Deleting Log File via HTTP API
$ curl -X DELETE http://selenoid-host.example.com:4444/logs/<filename>.log

2.3. Uploading Files To Browser

Some tests require to upload files. This feature works out of the box in the majority of Selenium clients. A typical Java code snippet look like the following:

Uploading files with Java
// Find file input element
WebElement input = driver.findElement(By.cssSelector("input[type='file']"));

// Make sure element is visible
((JavascriptExecutor) driver).executeScript("arguments[0].style.display = 'block';", input);

// Configure your client to upload local files to remote Selenium instance
driver.setFileDetector(new LocalFileDetector());

// Specify you local file path here (not path inside browser container!)
input.sendKeys("/path/to/file/on/machine/which/runs/tests");
Uploading files with Python
from selenium.webdriver.remote.file_detector import LocalFileDetector

# ...

input = driver.find_element_by_css_selector("input[type='file']")
driver.execute_script("arguments[0].style.display = 'block';", input)
driver.file_detector = LocalFileDetector()
input.send_keys("/path/to/file/on/machine/which/runs/tests")
Uploading files with Webdriver.io
var filePath = path.join('/path/to/file/on/machine/which/runs/tests');
var remoteFilePath = browser.uploadFile(filePath);
$("input[type='file']").setValue(remoteFilePath);

Read the following note if you are using Selenoid without Docker.

This feature is supported in WebDriver protocol by sending zipped file contents to /file handle. However not all driver binaries support this feature. For example this is not implemented in Geckodriver or IEDriver. When proxying requests directly to these drivers (i.e. when not using Docker) you need to start Selenoid with -enable-file-upload flag. In that case Selenoid will provide required API to tests. Firefox container images already include this parameter where needed.

2.4. Downloading Files From Browser

2.4.1. Downloading Files in Different Browsers

Chrome
Downloading files with Java
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setExperimentalOption("prefs", new HashMap<String, Object>(){
    {
        put("profile.default_content_settings.popups", 0);
        put("download.default_directory", "/home/selenium/Downloads");
        put("download.prompt_for_download", false);
        put("download.directory_upgrade", true);
        put("safebrowsing.enabled", false);
        put("plugins.always_open_pdf_externally", true);
        put("plugins.plugins_disabled", new ArrayList<String>(){
            {
                add("Chrome PDF Viewer");
            }
        });
    }
});

WebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), chromeOptions);
driver.navigate().to("http://example.com/myfile.odt");
Firefox
Downloading files with Java
FirefoxOptions firefoxOptions = new FirefoxOptions();
firefoxOptions.setCapability("moz:firefoxOptions", new HashMap<String, Object>(){
    {
        put("prefs", new HashMap<String, Object>(){
            {
                put("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream");
            }
        });
    }
});


WebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), firefoxOptions);
driver.navigate().to("http://example.com/myfile.odt");

2.4.2. Accessing Files Downloaded with Browser

  1. This feature only works when browsers are being run in containers.

  2. Files are accessible only when browser session is running.

Your tests may need to download files with browsers. To analyze these files a common requirement is then to somehow extract downloaded files from browser containers. A possible solution can be dealing with container volumes. But Selenoid provides a /download API and dramatically simplifies downloading files. Having a running session f2bcd32b-d932-4cdc-a639-687ab8e4f840 you can access all downloaded files using an HTTP request:

GET http://selenoid-host.example.com:4444/download/f2bcd32b-d932-4cdc-a639-687ab8e4f840/myfile.txt

In order for this feature to work an HTTP file server should be listening inside browser container on port 8080. Download directory inside container to be used in tests is usually ~/Downloads.

Similarly to delete downloaded files replace GET request with DELETE:

DELETE http://selenoid-host.example.com:4444/download/f2bcd32b-d932-4cdc-a639-687ab8e4f840/myfile.txt

2.5. Accessing Clipboard

Clipboard is accessible only when browser session is running.

Sometimes you may need to interact with the clipboard to check that your application copy-paste feature works. Selenoid has a dedicated API to interact with the clipboard. To use it:

  1. Start a new session, for example with ID f2bcd32b-d932-4cdc-a639-687ab8e4f840.

  2. To get clipboard value send the following HTTP request:

    $ curl http://selenoid-host.example.com:4444/clipboard/f2bcd32b-d932-4cdc-a639-687ab8e4f840
    
    some-clipboard-value
  3. To update clipboard value:

    $ curl -X POST --data 'some-clipboard-value' http://selenoid-host.example.com:4444/clipboard/f2bcd32b-d932-4cdc-a639-687ab8e4f840

2.6. Accessing Browser Developer Tools

  1. Currently only Chrome Developer Tools are supported.

  2. This feature will work only for Chrome 63+.

  3. We recommend to use the most recent Chrome version possible.

Selenoid is proxying Chrome Developer Tools API to browser container. For every running Selenium session to access the API just use the following URL:

<ws or http>://selenoid.example.com:4444/devtools/<session-id>/<method>

Here <method> is one of the following:

Table 1. Supported Developer Tools Methods

Method

Protocol

Meaning

/browser

WebSocket

Developer Tools browser websocket

/

WebSocket

An alias for /browser

/page

WebSocket

Developer Tools current page (target) websocket - mainly useful when only one browser tab is open

/page/<target-id>

WebSocket

Developer Tools specified page (target) websocket - allows to connect to concrete browser tab

/json/protocol

HTTP

A list of supported Developer Tools protocol methods in JSON format (some client libraries are using it)

For example an URL to connect to current page websocket would be:

ws://selenoid.example.com:4444/devtools/<session-id>/page
Accessing Developer Tools API with Webdriver.io and Puppeteer
const { remote } = require('webdriverio');
const puppeteer = require('puppeteer-core');
const host = 'selenoid.example.com';
(async () => {
    const browser = await remote({
        hostname: host,
        capabilities: {
            browserName: 'chrome',
            browserVersion: '75.0'
        }
    });

    const devtools = await puppeteer.connect(
        { browserWSEndpoint: `ws://${host}:4444/devtools/${browser.sessionId}` }
    );
    const page = await devtools.newPage();
    await page.goto('http://aerokube.com');
    await page.screenshot({path: 'screenshot.png'});
    const title = await page.title();

    console.log(title);

    await devtools.close();
    await browser.deleteSession();

})().catch((e) => console.error(e));

2.7. Special Capabilities

Selenoid can improve some automation aspects with custom capabilities. You can pass it in tests to enable/disable some features.

2.7.1. Live Browser Screen: enableVNC

Selenoid supports showing browser screen during test execution. This works with containers having VNC server installed (VNC column of Browser Image information). To see browser screen:

Type: boolean
enableVNC: true

Then launch Selenoid UI to see the screen.

This works by proxying VNC port from started container to http://localhost:4444/vnc/<session-id>; to WebSocket, where <session-id> is Selenium session ID.

2.7.2. Custom Screen Resolution: screenResolution

Selenoid allows you to set custom screen resolution in containers being run:

Type: string, format: <width>x<height>x<colors-depth>
screenResolution: "1280x1024x24"
  • This capability sets only screen resolution - not browser window size. Most of browsers have some default window size value this is why your screenshot size can be smaller than screen resolution specified in capability. You should manually resize window to desired width and height.

  • So far as our containers run headless browsers in Xvfb without installed window manager maximize operation does not work. You need to use setSize method instead.

2.7.3. Video Recording: enableVideo, videoName, videoScreenSize, videoFrameRate, videoCodec

This feature requires some preparation. Please refer to Video Recording section for more details.

To enable video recording for session, add:

Type: boolean
enableVideo: true
  • By default saved video files are named <session-id>.mp4 where <session-id> is a unique identifier of Selenium session. To provide custom video name specify:

    Type: string
    videoName: "my-cool-video.mp4"
    It is important to add mp4 file extension.
  • By default the entire screen picture is being recorded. Specifying screenResolution capability changes recorded video size (width and height) accordingly. You can override video screen size by passing a capability. In case of videoScreenSize resolution is less than actual, screen on video will be trimmed starting from top-left corner:

    Type: string
    videoScreenSize: "1024x768"
  • Default video frame rate is 12 frames per second. Specifying videoFrameRate capability changes this value:

    Type: int
    videoFrameRate: 24
  • By default Selenoid is using libx264 codec for video output. If this codec is consuming too much CPU, you can change it using videoCodec capability:

    Type: string
    videoCodec: "mpeg4"

    To obtain the full list of supported values:

    $ docker run -it --rm --entrypoint /usr/bin/ffmpeg selenoid/video-recorder -codecs

2.7.4. Saving Session Logs: enableLog, logName

This feature requires some preparation. Please refer to Saving Session Logs section for more details.

To enable saving logs for a session, add:

Type: boolean
enableLog: true

If you wish to automatically save logs for all sessions, you can enable this behavior globally with Selenoid -save-all-logs flag.

By default saved log files are named <session-id>.log where <session-id> is a unique identifier of Selenium session. To provide custom log file name specify:

Type: string
logName: "my-cool-log.log"
It is important to add log file extension.

2.7.5. Custom Test Name: name

For debugging purposes it is often useful to give a distinct name to every test case. When working with Selenoid you can set test case name by passing the following capability:

Type: string
name: "myCoolTestName"

The main application of this capability - is debugging tests in the UI which is showing specified name for every running session.

2.7.6. Custom Session Timeout: sessionTimeout

Sometimes you may want to change idle timeout for selected browser session. To achieve this - pass the following capability:

Type: string
sessionTimeout: 30m

Timeout is specified Golang duration format e.g. 30m or 10s or 1h5m and can be no more than the value set by -max-timeout flag.

2.7.7. Per-session Time Zone: timeZone

Some tests require particular time zone to be set in operating system. To achieve this with Selenoid use:

Type: string
timeZone: "Europe/Moscow"

You can find most of available time zones here. Without this capability launched browser containers will have the same timezone as Selenoid one.

2.7.8. Per-session Environment Variables: env

Sometimes you may want to set some environment variables for every test case (for example to test with different default locales). To achieve this pass one more capability:

Type: array, format: <key>=<value>
env: ["LANG=ru_RU.UTF-8", "LANGUAGE=ru:en", "LC_ALL=ru_RU.UTF-8"]

Environment variables from this capability are appended to variables from configuration file.

Sometimes you may need to link browser container to application container running on the same host machine. This allows you to use cool URLs like http://my-cool-app/ in tests. To achieve this simply pass information about one or more desired links via capability:

Type: array, format: <container-name>[:alias]
applicationContainers: ["spring-application-main:my-cool-app", "spring-application-gateway"]

2.7.10. Hosts Entries: hostsEntries

Although you can configure a separate list of /etc/hosts entries for every browser image in Browsers Configuration File sometimes you may need to add more entries for particular test cases. This can be easily achieved with:

Type: array, format: <hostname>:<ip-address>
hostsEntries: ["example.com:192.168.0.1", "test.com:192.168.0.2"]

Entries will be inserted to /etc/hosts before entries from browsers configuration file. Thus entries from capabilities override entries from configuration file if some hosts are equal.

2.7.11. Custom DNS Servers: dnsServers

By default Selenoid browser containers are using global DNS settings of Docker daemon. Sometimes you may need to override used DNS servers list for particular test cases. This can be easily achieved with:

Type: array, format: <dns-ip-address>
dnsServers: ["192.168.0.1", "192.168.0.2"]

2.7.12. More Docker Networks: additionalNetworks

By default Selenoid browser containers are started in Docker network specified by -container-network flag. If you tested application is running in another network you may need to connect browser container to this network:

Type: array, format: <network-name>
additionalNetworks: ["my-custom-net-1", "my-custom-net-2"]

2.7.13. Container Labels: labels

In big clusters you may want to pass additional metadata to every browser session: environment, VCS revision, build number and so on. These labels can be then used to enrich session logs and send them to a centralized log storage. Later this metadata can be used for more efficient search through logs.

Type: map, format: "<key>": "<value>"
labels: {"environment": "testing", "build-number": "14353"}

Labels from this capability override labels from browsers configuration file. When name capability is specified - it is automatically added as a label to container.

2.7.14. Android Skin: skin

For [Android] containers you can select emulator skin with capabilities. List of available skins:

Table 2. Available Android Skins
Skin Screen Resolution DPI

QVGA

240x320

120

WQVGA400

240x400

120

WQVGA432

240x432

120

HVGA

320x480

160

WVGA800

480x800

240

WVGA854

480x854

240

WSVGA

1024x600

160

WXGA720

720x1280

320

WXGA800

1280x800

160

WXGA800-7in

800x1280

213

To select a skin - set skin capability:

Type: string, format: <desired-skin>
skin: "WXGA720"

You can also pass desired screen resolution as follows:

Type: string, format: <desired-screen-resolution>
skin: "720x1280"

2.7.15. S3 Key Pattern: s3KeyPattern

This capability allows to override S3 key pattern (specified by -s3-key-pattern flag) used when uploading files to S3.

Type: string
s3KeyPattern: "$quota/$fileType$fileExtension"

The same key placeholders are supported. Please refer to Uploading Files To S3 section for more details.

2.7.16. Specifying Capabilities via Protocol Extensions

Some Selenium clients allow passing only a limited number of capabilities specified in WebDriver specification. For such cases Selenoid supports reading capabilities using WebDriver protocol extensions feature. The following two examples deliver the same result. Usually capabilities are passed like this:

Passing Capabilities as Usually
{"browserName": "firefox", "version": "57.0", "screenResolution": "1280x1024x24"}

Selenoid is using selenoid:options key to read protocol extension capabilities:

Passing Capabilities using Protocol Extensions
{"browserName": "firefox", "version": "57.0", "selenoid:options": {"screenResolution": "1280x1024x24"}}

3. Advanced Features

3.1. Usage Statistics

Selenoid calculates usage statistics that can be accessed with HTTP request:

Request
$ curl http://localhost:4444/status
Result
{
    "total": 80,
    "used": 10,
    "queued": 0,
    "pending": 1,
    "browsers": {
      "firefox": {
        "46.0": {
          "user1": {
            "count":1,
            "sessions":[
                {
                    "id": "a7a2b801-21db-4dae-a99b-4cbc0b81de96",
                    "vnc": false,
                    "screen": "1920x1080x24"
                 }
            ]
          },
          "user2": {
            "count":6,
            "sessions":[
                //...
            ]
          },
        },
        "48.0": {
          "user2": {
            "count":3,
            "sessions":[
                //...
            ]
          }
        }
      }
    }
}

Users are extracted from basic HTTP authentication headers.

3.1.1. What Statistics Mean

A typical session lifecycle looks like the following:

Typical Session Lifecycle

lifecycle

  1. A new session request arrives to Selenoid.

  2. Selenoid -limit flag specifies how many sessions can be created simultaneously. It is shown as total in statistics. When requests reach the limit - subsequent requests are placed in queue. Queued requests just block and continue to wait.

  3. When there is a free slot for request Selenoid decides whether a Docker container or standalone driver process should be created. All requests during startup are marked as pending. Before proceeding to next step Selenoid waits for required port to be open. This is done by sending HEAD requests to the port.

  4. When a container or driver is started (ping is successful) Selenoid does a new session request just in the same way as standard Selenium client.

  5. Depending on what is returned as response on the previous step session is marked as created or failed. Created and running sessions are also included to used value.

  6. When a session is created Selenoid just proxies the rest of session requests to the same container or driver.

  7. New session request can fail because of Selenium errors or issues with container \ driver startup. In that case an error is returned to user.

3.1.2. Sending Statistics to External Systems

To send Selenoid statistics described in previous section you can use Telegraf. For example to send status to Graphite:

  1. Pull latest Telegraf Docker container:

    # docker pull telegraf:alpine
  2. Generate configuration file:

    # mkdir -p /etc/telegraf
    # docker run --rm telegraf:alpine   \
        --input-filter httpjson         \
        --output-filter graphite config > /etc/telegraf/telegraf.conf
  3. Edit file like the following:

    [agent]
    interval = "10s" (1)
    
    [[outputs.graphite]]
    servers = ["my-graphite-host.example.com:2024"] (2)
    prefix = "one_min" (3)
    template = "host.measurement.field"
    
    [[inputs.httpjson]]
    name = "selenoid"
    servers = [
    "http://localhost:4444/status" (4)
    ]
    1 adjust interval if needed
    2 adjust host and port
    3 something before hostname, can be blank
    4 this is localhost only if Telegraf is run on Selenoid host
  4. Start Telegraf container:

    # docker run --net host -d  \
        --name telegraf         \
        -v /etc/telegraf:/etc   \
        telegraf:alpine --config /etc/telegraf.conf

    Metrics will be sent to my-graphite-host.example.com:2024. Metric names will be like the following:

    one_min.selenoid_example_com.httpjson_selenoid.pending
    one_min.selenoid_example_com.httpjson_selenoid.queued
    one_min.selenoid_example_com.httpjson_selenoid.total

telegraf+influxdb+graphana

3.2. Uploading Files To S3

This feature only becomes available when Selenoid is compiled with s3 build tag (missing by default) as follows:

$ go build -tags s3

Selenoid can upload recorded video and log files for every running session to S3-compatible storage.

To enable this feature you need to specify S3 access information as follows:

$ ./selenoid -s3-endpoint https://s3.us-east-2.amazonaws.com -s3-region us-east-2 -s3-bucket-name my-bucket -s3-access-key <your-access-key> -s3-secret-key <your-secret-key>
If you omit -s3-access-key and -s3-secret-key flags then environment variables and shared credentials file are automatically tried as a fallback.

By default uploaded file name is preserved, i.e. S3 path is /<session-id>.log or /myCustomVideo.mp4. You can optionally provide your custom key pattern using -s3-key-pattern flag and a set of placeholders:

Table 3. S3 Key Placeholders
Placeholder Meaning

$browserName

Replaced by Selenium browser name capability value

$browserVersion

Replaced by Selenium browser version capability value

$date

Replaced by current date, e.g. 2018-11-01

$fileName

Replaced by source file name

$fileExtension

Replaced by source file extension

$fileType

Replaced by log for log files and video for video files

$platformName

Replaced by Selenium platform capability value

$quota

Replaced by quota name (usually coming from Ggr)

$sessionId

Replaced by Selenium session ID

For example, when launching Selenoid with -s3-key-pattern $browserName/$sessionId/log.txt files will be accessible as firefox/0ee0b48b-e29b-6749-b4f1-2277b8f8d6c5/log.txt. You can also override key pattern for every session with s3KeyPattern capability.

Sometimes you may want to upload only video files or files matching some complicated pattern or to not upload some files. To achieve this use -s3-include-files and -s3-exclude-files flags. These flags accept globs such as *.mp4.

3.3. Saving Session Metadata

This feature only becomes available when Selenoid is compiled with metadata build tag (missing by default).

Selenoid can save session metadata to a separate JSON file. Main use case is to somehow post-process session logs, e.g. send them to map-reduce cluster. No additional configuration is needed to enable this feature. When enabled and -log-output-dir flag is set - Selenoid will automatically save JSON files <log-output-dir>/<session-id>.json with the following content:

Example metadata JSON file
{
    "id": "62a4d82d-edf6-43d5-886f-895b77ff23b7",
    "capabilities": {
        "browserName": "chrome",
        "version": "70.0",
        "name": "MyCoolTest",
        "screenResolution": "1920x1080x24"
    },
    "started": "2018-11-15T16:23:12.440916+03:00",
    "finished": "2018-11-15T16:23:12.480928+03:00"
}

3.4. Using Selenoid without Docker

Selenoid is using containers to start browsers. However cases exist when running browser in container is not possible. For example on Windows you have Internet Explorer which can not be run inside container. Selenoid can be used as a lightweight Selenium server replacement to run IE, Firefox or Chrome on Windows. For example to use Selenoid with IE:

  1. Download latest IEDriverServer archive and unpack it to some directory (C:\ in this example).

  2. Download latest Selenoid binary.

  3. Create browsers.json configuration file:

    {
      "internet explorer": {
        "default": "11",
        "versions": {
          "11": {
            "image": ["C:\\IEDriverServer.exe", "--log-level=DEBUG"]
          }
        }
      }
    }

    Notice that backslashes in Windows paths should be escaped as \\. In this example we define a browser with name internet explorer and version 11.

  4. Start Selenoid:

    ./selenoid_win_amd64.exe -conf ./browsers.json -disable-docker
  5. Run your tests against ...

    http://localhost:4444/wd/hub

    ... with the following capabilities:

    browserName = internet explorer
    version = 11
  6. To start Chrome instead just download Chromedriver binary and modify browsers.json accordingly.

  7. By default Selenoid does not process launched driver logs. Launch Selenoid with -capture-driver-logs flag to append driver logs for every session to main log.

4. Configuration

  • We recommend to use latest Docker release and Linux core 4.x and above. Older kernels and Docker releases have known bugs.

  • Use modern OverlayFS Docker storage driver. AUFS is also fast but has some bugs that can lead to orphaned containers. Never use Device Mapper - it is very slow. See this page on how to adjust Docker storage driver. To check your currently used driver type:

    # docker info | grep Storage
  • Total number of simultaneously running containers (adjusted via -limit flag) depends on your host machine hardware. Our experience shows that depending on your tests the recommended limit is something like: 1.5-2.0 x numCores, where numCores is total number of cores on your host machine.

  • In some Docker installations you can see random Selenium commands failing because of the timeout. This is mainly caused by low bridged networking (aka docker0) performance. To avoid this we recommend to set docker0 network Mac-address to the same value as eth0 has:

    # ifconfig | grep eth0
    eth0      Link encap:Ethernet  HWaddr 00:25:90:eb:fb:3e

    Now we are setting this Mac-address for docker0 virtual interface:

    # ip link set docker0 address 00:25:90:eb:fb:3e

    To make these settings permanent we need to adding the following line to docker0 section in /etc/network/interfaces:

    iface docker0 inet static
            # ... the rest of lines
            post-up ip link set docker0 address 00:25:90:eb:fb:3e
  • You may also want to limit memory and CPU consumption for each started container. To do this use -mem and -cpu flags. For example to limit memory type:

    # ./selenoid -mem 128m

    Here values are specified in Docker format. Similarly to limit CPU comsumption specify total number of CPUs per container as a float:

    # ./selenoid -cpu 1.5
  • We use the same client as docker command does. This is why all environment variables like DOCKER_API_VERSION or DOCKER_CERT_PATH are applicable. See full list of supported variables in Docker documentation. For example you may encounter the following error when running Selenoid:

    [SERVICE_STARTUP_FAILED] [unknown] [create container: Error response from daemon: client is newer than server (client API version: 1.30, server API version: 1.24)]

    This is because your Docker server version is older than Selenoid client version. To fix this you need to switch Selenoid to use supported API version - 1.24. This can be done by setting DOCKER_API_VERSION environment variable:

    # docker run -e DOCKER_API_VERSION=1.24 -d --name selenoid -p 4444:4444 -v /etc/selenoid:/etc/selenoid:ro -v /var/run/docker.sock:/var/run/docker.sock aerokube/selenoid:latest-release

4.2. Browsers Configuration File

Selenoid requires a simple JSON configuration file of the following format:

browsers.json
{
    "firefox": {                                     (1)
      "default": "46.0",                             (2)
      "versions": {                                  (3)
        "46.0": {                                    (4)
          "image": "selenoid/firefox:46.0",          (5)
          "port": "4444",                            (6)
          "tmpfs": {"/tmp": "size=512m"},            (7)
          "path" : "/wd/hub",                        (8)
          "volumes" : ["/from:/to:ro"],              (9)
          "env" : ["TZ=Europe/Moscow"],              (10)
          "hosts" : ["example.com:192.168.0.1"],     (11)
          "shmSize" : 268435456,                     (12)
          "cpu" : "1.0",                             (13)
          "mem" : "512m",                            (14)
        },
        "50.0" :{
            // ...
        }
      }
    },
    "chrome": {
        // ...
    }
}
1 Browser name
2 Default browser version
3 A list of available browser versions
4 Version name
5 Image name or driver binary command
6 Containers only. Port to proxy connections to, see below
7 Optional. Containers only. Add in-memory filesystem (tmpfs) to container, see below
8 Optional. Path relative to / where we request a new session, see below
9 Optional. Containers only. Mount path from host machine to created container
10 Optional. Environment variables to be passed to browser container or driver process
11 Optional. Custom /etc/hosts entries to be passed to browser container in hostname:ip format.
12 Optional. Shared memory size in bytes to be set for container. Some browsers (e.g. Chrome) may work unstable when having insufficient shmSize. Default value is 256 megabytes.
13 Optional. Containers only. Container CPU limit in Docker units.
14 Optional. Containers only. Container memory limit in Docker units.

This file represents a mapping between a list of supported browser versions and Docker container images or driver binaries.

To use custom browsers configuration file - use -conf flag:

$ ./selenoid -conf /path/to/browsers.json

4.2.1. Browser Name and Version

Browser name and version are just strings that are matched against Selenium desired capabilities:

  • browserName

  • version

If no version capability is present default version is used. When there is no exact version match we also try to match by prefix. That means version string in JSON should start with version string from capabilities.

Example 2. Matching Logic
in browsers.json
"versions": {
   "46.0": {

Version capability that will match:

version = 46 (46.0 starts with 46)

Will not match:

version = 46.1 (46.0 does not start with 46.1)

4.2.2. Image

Image by default is a string with container specification in Docker format (hub.example.com/project/image:tag).

Image must be already pulled. Configuration Manager can help with this task.

Example 3. Valid images

Pulled from internal docker registry:

my-internal-docker-hub.example.com/selenoid/firefox:46.0

Pulled from hub.docker.com

selenoid/firefox:46.0

Standalone Binary

If you wish to use a standalone binary instead of Docker container, then image field should contain command specification in square brackets:

"46.0": {
    "image": ["/usr/bin/mybinary", "-arg1", "foo", "-arg2", "bar", "-arg3"],
    "port": "4444"
},

Selenoid proxies connections to either Selenium server or standalone driver binary. Depending on operating system both can be packaged inside Docker container.

4.2.3. Other Optional Fields

"46.0": {
    //...
    "port": "",
    "tmpfs": {"/tmp": "size=512m", "/var": "size=128m"},
    "path" : "",
    "volumes": ["/from:/to", "/another:/one:ro"],
    "env" : ["TZ=Europe/Moscow", "ONE_MORE_VARIABLE=itsValue"],
    "hosts" : ["one.example.com:192.168.0.1", "two.example.com:192.168.0.2"],
    "labels" : {"component": "frontend", "project": "my-project"},
    "sysctl" : {"net.ipv4.tcp_timestamps": "2", "kern.maxprocperuid": "1000"},
    "shmSize" : 268435456,
},
  • port (only for containers) - You should use port field to specify the real port inside container that container process (Selenium server, Selenoid or driver) will listen on.

  • tmpfs (optional) - You may probably know that moving browser cache to in-memory filesystem (Tmpfs) can dramatically improve its performance. Selenoid can automatically attach one or more in-memory filesystems as volumes to Docker container being run. To achieve this define one or more mount points and their respective sizes in optional tmpfs field.

  • path (optional) - path field is needed to specify relative path to the URL where a new session is created (default is /). Which value to specify in this field depends on container contents. For example, most of Firefox containers have Selenium server inside - thus you need to specify /wd/hub. Chrome and Opera containers use web driver binary as entrypoint application which is accepting requests at /. We recommend to use our configuration tool to avoid errors with this field.

  • volumes (optional) - This field allows to mount volumes from host machine to browser container. Should be specified as an array of Docker volume expressions: /host/dir:/container/dir[:mode].

  • env (optional) - This field allows to set any environment variables in running container. Specified as an array of NAME=value pairs.

  • hosts (optional) - This field allows to add custom /etc/hosts entries to running container. Specified as an array of hostname:ip pairs.

  • labels (optional) - This field allows to add custom labels to running container. Specified as an object of "key": "value" pairs.

  • sysctl (optional) - This field allows to adjust kernel parameters of running container. Specified as an object of "key": "value" pairs.

  • shmSize (optional) - Use it to override shared memory size for browser container.

4.2.4. Syncing Browser Images from Existing File

In some usage scenarios you may want to store browsers configuration file under version control and initialize Selenoid from this file. For example this is true if you wish to have consistently reproducing infrastructure and using such tools as Amazon Cloud Formation.

Why this is not the part of Selenoid? Well, this is easy to implement, but under heavy load the result can be unpredictable. For example after updating the file and reloading Selenoid it should pull new images. How long will you wait for new sessions then? What to do if Docker Registry is inaccessible? So for maintenance reasons it is easier to delegate such simple logic to external script.

In order to pull browser images use on of the following options:

Option 1: using CM

Recent CM tool versions are able to configure Selenoid from existing browsers.json file as follows:

# ./cm selenoid start --browsers-json /path/to/your/browsers.json

This way is mainly useful when installing Selenoid from scratch or updating it i.e. as a part of CI build job.

Option 2: using jq

  1. Install jq - a small tool to query data from JSON files.

  2. Extract image names from JSON and automatically pull them:

    # cat /path/to/browsers.json | jq -r '..|.image?|strings' | xargs -I{} docker pull {}

This way can be applied to a running cluster with tests with no downtime.

4.3. Logging Configuration File

By default Docker container logs are saved to host machine hard drive. When using Selenoid for local development that’s ok. But in big Selenium cluster you may want to send logs to some centralized storage like Logstash or Graylog. Docker provides such functionality by so-called logging drivers. An optional Selenoid logging configuration file allows to specify which logging driver to use globally for all started Docker containers with browsers. Configuration file has the following format:

config/container-logs.json
{
    "Type" : "<driver-type>",   (1)
    "Config" : {                (2)
      "key1" : "value1",
      "key2" : "value2"
    }
}
1 is a supported Docker logging driver type like syslog, journald or awslogs.
2 Config is a list of key-value pairs used to configure selected driver.

For example these Docker logging parameters:

--log-driver=syslog --log-opt syslog-address=tcp://192.168.0.42:123 --log-opt syslog-facility=daemon

... are equivalent to the following Selenoid logging configuration:

config/container-logs.json
{
    "Type" : "syslog",
    "Config" : {
      "syslog-address" : "tcp://192.168.0.42:123",
      "syslog-facility" : "daemon"
    }
}

To specify custom logging configuration file - use -log-conf flag:

$ ./selenoid -log-conf /path/to/logging.json ...

4.4. Reloading Configuration

To reload configuration without restart send SIGHUP:

# kill -HUP <pid>
# docker kill -s HUP <container-id-or-name>
Use only one of these commands.

To check Selenoid instance health use /ping:

Request
$ curl -s http://example.com:4444/ping
Result
{
    "uptime": "2m46.854829503s",
    "lastReloadTime": "2017-05-12 12:33:06.322038542 +0300 MSK",
    "numRequests": 42
}

It returns 200 OK when Selenoid operates normally. Additionally server uptime, last quota reload time and overall number of session requests from service startup are returned in JSON format.

4.5. Updating Browsers

One of the most frequent Selenoid maintenance tasks is updating browser versions. To modify the list of available browsers you need to:

  1. Update browsers configuration file (aka browsers.json) by adding or deleting desired browser versions

  2. When adding new browsers in containers - pull respective container images, e.g.:

    $ docker pull selenoid/chrome:62.0
  3. Restart Selenoid or hot reload its configuration.

4.5.1. The Short Way

This approach is mainly convenient for personal usage because Selenoid is restarted i.e. any running browser sessions are interrupted. Just type one Configuration Manager command:

$ ./cm selenoid update

This command will download latest Selenoid release, browser images, generate new browsers.json and restart Selenoid. You may want to add --vnc flag to download images with VNC support:

$ ./cm selenoid update --vnc

Another useful flag is total number of last browser versions to download (default is 2):

$ ./cm selenoid update --last-versions 5

If you wish to pull new images and regenerate configuration without restarting Selenoid then type:

$ ./cm selenoid configure --vnc --last-versions 5

4.5.2. A Bit Longer Way

We recommend to use this approach on production clusters because Selenoid configuration is reloaded without restart.

  1. Edit browsers.json file and pull new browsers containers manually or using Syncing Browser Images from Existing File. Alternatively configure Selenoid without restarting it like shown in previous section.

  2. Reload Selenoid configuration (see Reloading Configuration for more details):

    $ docker kill -s HUP selenoid
  3. To verify that configuration was reloaded you can check Selenoid health:

    $ curl -s http://example.com:4444/ping
    {"uptime":"<some-value>","lastReloadTime":"2017-05-12 12:33:06.322038542 +0300 MSK","numRequests":<some-number>}

    Here lastReloadTime field shows when browsers configuration was reloaded for the last time.

4.6. Setting Timezone

When used in Docker container Selenoid will have timezone set to UTC. To set custom timezone pass TZ environment variable to Docker:

$ docker run -d --name selenoid                     \
    -p 4444:4444                                    \
    -e TZ=Europe/Moscow                             \
    -v /etc/selenoid:/etc/selenoid:ro               \
    -v /var/run/docker.sock:/var/run/docker.sock    \
    aerokube/selenoid:latest-release

4.7. Selenoid with Docker Compose

In example Docker Compose configurations below we assume that:

  1. You created a directory /path/to/config with Browsers Configuration File inside named browsers.json.

    $ mkdir -p /path/to/config
  2. You created empty configuration directories for logs and videos:

    $ mkdir -p /path/to/config/logs
    $ mkdir -p /path/to/config/video

4.7.1. Option 1. Running Selenoid in default Docker network

In that case bridge network mode should be used for all services:

version: '3'
services:
  selenoid:
    network_mode: bridge
    image: aerokube/selenoid:latest-release
    volumes:
      - "/path/to/config:/etc/selenoid"
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/path/to/config/video:/opt/selenoid/video"
      - "/path/to/config/logs:/opt/selenoid/logs"
    environment:
      - OVERRIDE_VIDEO_OUTPUT_DIR=/path/to/config/video
    command: ["-conf", "/etc/selenoid/browsers.json", "-video-output-dir", "/opt/selenoid/video", "-log-output-dir", "/opt/selenoid/logs"]
    ports:
      - "4444:4444"

4.7.2. Option 2. Running Selenoid in custom Docker network

In that case you have to add -container-network flag to Selenoid as follows:

  1. Create custom Docker network:

    $ docker network create selenoid
  2. Start Selenoid:

version: '3'
networks:
  selenoid:
    external:
      name: selenoid # This assumes network is already created
services:
  selenoid:
    networks:
      selenoid: null
    image: aerokube/selenoid:latest-release
    volumes:
      - "/path/to/config:/etc/selenoid"
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/path/to/config/video:/opt/selenoid/video"
      - "/path/to/config/logs:/opt/selenoid/logs"
    environment:
      - OVERRIDE_VIDEO_OUTPUT_DIR=/path/to/config/video
    command: ["-conf", "/etc/selenoid/browsers.json", "-video-output-dir", "/opt/selenoid/video", "-log-output-dir", "/opt/selenoid/logs", "-container-network", "selenoid"]
    ports:
      - "4444:4444"

4.8. Log Files

A typical log file looks like the following:

2017/11/01 19:12:38 [-] [NEW_REQUEST]
2017/11/01 19:12:38 [-] [NEW_REQUEST_ACCEPTED]
2017/11/01 19:12:38 [41301] [LOCATING_SERVICE] [firefox-45.0]
2017/11/01 19:12:38 [41301] [USING_DOCKER] [firefox-45.0]
2017/11/01 19:12:38 [41301] [CREATING_CONTAINER] [selenoid/firefox:45.0]
2017/11/01 19:12:38 [41301] [STARTING_CONTAINER] [selenoid/firefox:45.0] [19760edf330a87531eb2109cfbf1bd4b14c739afa08fe133eb1b9813b2ac6c31]
2017/11/01 19:12:39 [41301] [CONTAINER_STARTED] [selenoid/firefox:45.0] [19760edf330a87531eb2109cfbf1bd4b14c739afa08fe133eb1b9813b2ac6c31] [896.680954ms]
2017/11/01 19:12:40 [41301] [SERVICE_STARTED] [selenoid/firefox:45.0] [19760edf330a87531eb2109cfbf1bd4b14c739afa08fe133eb1b9813b2ac6c31] [605.184606ms]
2017/11/01 19:12:40 [41301] [PROXY_TO] [selenoid/firefox:45.0] [19760edf330a87531eb2109cfbf1bd4b14c739afa08fe133eb1b9813b2ac6c31] [http://172.17.0.3:4444/wd/hub]
2017/11/01 19:12:40 [41301] [SESSION_ATTEMPTED] [test-quota] [http://172.17.0.3:4444/wd/hub] [1]
2017/11/01 19:12:42 [41301] [SESSION_CREATED] [test-quota] [345bb886-7026-46d7-82d4-4788c0460110] [http://172.17.0.3:4444/wd/hub] [1] [4.155712239s]
....
2017/11/01 19:14:30 [SESSION_DELETED] [345bb886-7026-46d7-82d4-4788c0460110]

Every line contains:

Table 4. Log entry contents
Field Example Notes

Time

2017/11/01 19:12:42

-

Request counter

[41301]

So far as session ID is unknown when doing attempts this counter is used to find all session attempts for each new session request.

Status

[SESSION_ATTEMPTED]

See table below for complete list of statuses.

Browser

[firefox-45.0]

Name and version. Only present for new session requests.

Attempt number

[1]

For SESSION_ATTEMPTED entries means current attempt number. For SESSION_CREATED entries means total number of attempts to create this session.

Session ID

[345bb886-7026-46d7-82d4-4788c0460110]

This value is unique for every browser session

Session start time

[4.15s]

-

The following statuses are available:

Table 5. Log entry statuses
Status Description

ALLOCATED_PORT

Successfully allocated port for driver process

ALLOCATING_PORT

Trying to allocate random free port for driver process

BAD_JSON_FORMAT

User request does not contain valid Selenium data

BAD_SCREEN_RESOLUTION

User requested to set wrong custom screen resolution

BAD_TIMEZONE

User requested to set wrong custom time zone inside container

BAD_VIDEO_SCREEN_SIZE

User requested to capture video with wrong screen size

CLIENT_DISCONNECTED

User disconnected and session was interrupted

CONTAINER_LOGS

User requested container logs

CONTAINER_LOGS_ERROR

User requested container logs

CONTAINER_LOGS_DISCONNECTED

User logs client disconnected

CONTAINER_REMOVED

Docker container was successfully removed

CONTAINER_STARTED

Docker container has successfully started

FAILED_TO_COPY_LOGS

Failed to copy logs from Docker container

CREATING_CONTAINER

Docker container with browser is creating

DEFAULT_VERSION

Selenoid is using default browser version

DELETED_LOG_FILE

Log file was deleted by user

DELETED_VIDEO_FILE

Video file was deleted by user

DEVTOOLS_CLIENT_DISCONNECTED

User devtools client disconnected

DEVTOOLS_DISABLED

An attempt to access browser devtools when it is not enabled with capability

DEVTOOLS_ERROR

An error occurred when trying to send devtools traffic

DEVTOOLS_SESSION_CLOSED

Sending devtools traffic was stopped

DOWNLOADING_FILE

User requested to download file from browser container

ENVIRONMENT_NOT_AVAILABLE

Browser with desired name and version does not exist

FAILED_TO_REMOVE_CONTAINER

Failed to remove Docker container

FAILED_TO_TERMINATE_PROCESS

An error occurred while terminating driver process

INIT

Server is starting

LOG_LISTING

Received a request to list all log files

LOG_ERROR

An error occurred when post-processing session logs

METADATA

Metadata processing messages

NEW_REQUEST

New user request arrived and was placed to queue

NEW_REQUEST_ACCEPTED

Started processing new user request

PROCESS_STARTED

Driver process successfully started

PROXY_TO

Starting to proxy requests to running container or driver process

REMOVING_CONTAINER

Docker container with browser or video recorder is being removed

SERVICE_STARTED

Successfully started Docker container or driver binary

SERVICE_STARTUP_FAILED

Failed to start Docker container or driver binary

SESSION_ATTEMPTED

Started Docker container or driver binary and trying to create a new session with it

SESSION_ATTEMPT_TIMED_OUT

An attempt to create a new session timed out

SESSION_CREATED

A new session was created and returned to user

SESSION_TIMED_OUT

Existing session was terminated by timeout

SESSION_DELETED

Existing session was deleted by user request

SESSION_FAILED

An attempt to create a new session failed - user receives an error

SESSION_NOT_FOUND

Requested VNC or logs for unknown session.

STARTING_CONTAINER

Docker container with browser was created and is starting

STARTING_PROCESS

Starting driver process

SHUTTING_DOWN

Server is stopping

TERMINATING_PROCESS

Stopping driver process

TERMINATED_PROCESS

Driver process was successfully stopped

UPLOADING_FILE

An issue occurred while uploading file

UPLOADED_FILE

File successfully uploaded

VIDEO_LISTING

Received a request to list all videos

VIDEO_ERROR

An error occurred when post-processing recorded video

VNC_CLIENT_DISCONNECTED

User VNC client disconnected

VNC_ENABLED

User requested VNC traffic

VNC_ERROR

An error occurred when trying to send VNC traffic

VNC_SESSION_CLOSED

Sending VNC traffic was stopped

VNC_NOT_ENABLED

User requested VNC traffic but did not specify enableVNC capability

4.9. Selenoid CLI Flags

The following flags are supported by selenoid command:

-capture-driver-logs
    Whether to add driver process logs to Selenoid output
-conf string
    Browsers configuration file (default "config/browsers.json")
-container-network string
    Network to be used for containers (default "default")
-cpu value
    Containers cpu limit as float e.g. 0.2 or 1.0
-disable-docker
    Disable docker support
-disable-privileged
    Whether to disable privileged container mode
-disable-queue
    Disable wait queue
-enable-file-upload
    File upload support
-graceful-period duration
    graceful shutdown period in time.Duration format, e.g. 300s or 500ms (default 5m0s)
-limit int
    Simultaneous container runs (default 5)
-listen string
    Network address to accept connections (default ":4444")
-log-conf string
    Container logging configuration file
-log-output-dir string
    Directory to save session log to
-max-timeout duration
    Maximum valid session idle timeout in time.Duration format (default 1h0m0s)
-mem value
    Containers memory limit e.g. 128m or 1g
-retry-count int
    New session attempts retry count (default 1)
-save-all-logs
    Whether to save all logs without considering capabilities
-service-startup-timeout duration
    Service startup timeout in time.Duration format (default 30s)
-session-attempt-timeout duration
    New session attempt timeout in time.Duration format (default 30s)
-session-delete-timeout duration
    Session delete timeout in time.Duration format (default 30s)
-timeout duration
    Session idle timeout in time.Duration format (default 1m0s)
-version
    Show version and exit
-video-output-dir string
    Directory to save recorded video to (default "video")
-video-recorder-image string
    Image to use as video recorder (default "selenoid/video-recorder:latest-release")

For example:

$ ./selenoid -conf ~/.aerokube/selenoid/browsers.json -limit 10

When using Selenoid inside Docker container these flags are passed like the following:

# docker run -d --name selenoid                     \
    -p 4444:4444                                    \
    -v ~/.aerokube/selenoid/:/etc/selenoid/:ro      \
    -v /var/run/docker.sock:/var/run/docker.sock    \
    aerokube/selenoid:latest-release                \
    -conf /etc/selenoid/browsers.json -limit 10 -video-output-dir /opt/selenoid/video/

4.9.1. S3 CLI Flags

The following flags are supported by selenoid command when compiled with S3 support:

-s3-access-key string
    S3 access key
-s3-bucket-name string
    S3 bucket name
-s3-endpoint string
    S3 endpoint URL
-s3-exclude-files string
    Pattern used to match and exclude files
-s3-force-path-style
    Force path-style addressing for file upload
-s3-include-files string
    Pattern used to match and include files
-s3-keep-files
    Do not remove uploaded files
-s3-key-pattern string
    S3 bucket name (default "$fileName")
-s3-reduced-redundancy
    Use reduced redundancy storage class
-s3-region string
    S3 region
-s3-secret-key string
    S3 secret key

5. Contributing & Development

To build Selenoid:

  1. Install Golang 1.12 and above.

  2. Setup $GOPATH properly

  3. Clone Selenoid source:

    $ git clone https://github.com/aerokube/selenoid.git
  4. Go to project directory:

    $ cd selenoid
  5. Build source:

    $ go build

    This will also fetch build dependencies.

  6. Run Selenoid:

    $ ./selenoid --help

To build Docker container type:

$ mkdir -p dist
$ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o dist/selenoid_linux_amd64
$ docker buildx build --pull --platform linux/amd64 -t selenoid:latest .

5.1. Documentation

Locally can be generated with:

$ docker run --rm -v ./docs/:/documents/      \
    asciidoctor/docker-asciidoctor                \
    asciidoctor -D /documents/output/ index.adoc

Appendix A: Browser Image information

Moved to a dedicated page.