The project is made possible by volunteer contributors who have put in thousands of hours of their own time, and made the source code freely available under the Apache License 2.0.
These Docker images come with a handful of tags to simplify its usage, have a look at them in one of our releases.
To get notifications of new releases, add yourself as a "Releases only" watcher.
These images are published to the Docker Hub registry at Selenium Docker Hub.
Do you need help to use these Docker images? Talk to us at https://www.selenium.dev/support/
--shm-size="2g"
docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:4.26.0-20241101
Point your WebDriver tests to http://localhost:4444
That's it!
(Optional) To see what is happening inside the container, head to http://localhost:7900/?autoconnect=1&resize=scale&password=secret.
For more details about visualising the container activity, check the Debugging section.
☝️ When executing docker run
for an image that contains a browser please use
the flag --shm-size=2g
to use the host's shared memory.
☝️ Always use a Docker image with a full tag to pin a specific browser and Grid version. See Tagging Conventions for details.
From image tag based 4.21.0
onwards, the architectures supported by this project are as below:
Architecture | Available |
---|---|
x86_64 (aka amd64) | ✅ |
aarch64 (aka arm64/armv8) | ✅ |
armhf (aka arm32/armv7l) | ❌ |
The following browsers are available in multi-arch images:
Architecture | Chrome | Chromium | Firefox | Edge |
---|---|---|---|---|
x86_64 (aka amd64) | ✅ | ✅ | ✅ | ✅ |
aarch64 (aka arm64/armv8) | ❌ | ✅ | ✅ | ❌ |
armhf (aka arm32/armv7l) | ❌ | ❌ | ❌ | ❌ |
Note:
Google does not build Chrome (google-chrome
) for Linux/ARM platforms. Hence, the Chrome (node and standalone) images are only available for AMD64.
Similarly, Microsoft does not build Edge (microsoft-edge
) for Linux/ARM platforms.
Running an AMD64 image under emulation on an ARM64 platform is not recommended due to performance and stability issues.
For Linux/ARM use the open source Chromium browser. The Chromium (node and standalone) images are available in multi-arch.
$ docker run --rm -it -p 4444:4444 -p 5900:5900 -p 7900:7900 --shm-size 2g selenium/standalone-chromium:latest
Multi-arch images are tested on CircleCI with resource class Linux/ARM64. See the status below.
For experimental docker container images, which run on platforms such as the Apple M-series or Raspberry Pi, the repository at seleniumhq-community/docker-seleniarm provided images which are published on the Seleniarm Docker Hub registry.
See issue #1076 for more information on these images.
Now, the fork seleniumhq-community/docker-seleniarm was merged.
We recommend to enable the experimental feature containerd image store in Docker Engine.
containerd
understands multiplatform images, where a single image tag can refer to different variants covering a range of OS and hardware architectures.
It simplifies the process of building, storing, and distributing images across different platforms.
A single command to enable that feature in Docker Engine:
make set_containerd_image_store
To build all the images for multiplatform, run the following command:
PLATFORMS=linux/amd64,linux/arm64 make build
To build the images for a specific platform, run the following command:
PLATFORMS=linux/arm64 make build
By default, without specifying the PLATFORMS
variable, the images are built for the linux/amd64
platform.
Nightly images are built on top of the Nightly build on the upstream project Selenium with the latest changes on main branch in this repository. The image tag is nightly
. This is not recommended to use images in production. It is only for testing purpose.
$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:nightly
Check out the docker compose to get started with Nightly images docker-compose-v3-full-grid-nightly.yml
To run tests or otherwise work with pre-release browsers, Google, Mozilla, and Microsoft maintain a Dev and Beta release channel for those who need to see what's soon to be released to the general population.
Here are the instructions to run them in Standalone mode:
Chrome Beta:
$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:beta
Chrome Dev:
$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:dev
Firefox Beta:
$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:beta
Firefox Dev:
$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:dev
Edge Beta:
$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:beta
Edge Dev:
$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:dev
docker-compose-v3-beta-channel.yml:
# To execute this docker compose yml file use `docker compose -f docker-compose-v3-beta-channel.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker compose -f docker-compose-v3-beta-channel.yml down`
version: "3"
services:
chrome:
image: selenium/node-chrome:beta
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
edge:
image: selenium/node-edge:beta
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
firefox:
image: selenium/node-firefox:beta
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
selenium-hub:
image: selenium/hub:latest
container_name: selenium-hub
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
docker-compose-v3-dev-channel.yml:
# To execute this docker compose yml file use `docker compose -f docker-compose-v3-dev-channel.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker compose -f docker-compose-v3-dev-channel.yml down`
version: "3"
services:
chrome:
image: selenium/node-chrome:dev
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
edge:
image: selenium/node-edge:dev
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
firefox:
image: selenium/node-firefox:dev
shm_size: 2gb
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
selenium-hub:
image: selenium/hub:latest
container_name: selenium-hub
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
For more information on the Dev and Beta channel container images, see the blog post on Dev and Beta Channel Browsers via Docker Selenium.
Firefox
docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-firefox:4.26.0-20241101
Chrome
docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:4.26.0-20241101
Edge
docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-edge:4.26.0-20241101
Note: Only one Standalone container can run on port 4444
at the same time.
There are different ways to run the images and create a Grid with a Hub and Nodes, check the following options.
The Hub and Nodes will be created in the same network and they will recognize each other by their container name. A Docker network needs to be created as a first step.
$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.26.0-20241101
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub
--shm-size="2g"
-e SE_EVENT_BUS_PUBLISH_PORT=4442
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443
selenium/node-chrome:4.26.0-20241101
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub
--shm-size="2g"
-e SE_EVENT_BUS_PUBLISH_PORT=4442
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443
selenium/node-edge:4.26.0-20241101
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub
--shm-size="2g"
-e SE_EVENT_BUS_PUBLISH_PORT=4442
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443
selenium/node-firefox:4.26.0-20241101
$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.26.0-20241101
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
--shm-size="2g" `
-e SE_EVENT_BUS_PUBLISH_PORT=4442 `
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 `
selenium/node-chrome:4.26.0-20241101
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
--shm-size="2g" `
-e SE_EVENT_BUS_PUBLISH_PORT=4442 `
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 `
selenium/node-edge:4.26.0-20241101
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
--shm-size="2g" `
-e SE_EVENT_BUS_PUBLISH_PORT=4442 `
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 `
selenium/node-firefox:4.26.0-20241101
When you are done using the Grid, and the containers have exited, the network can be removed with the following command:
# Removes the grid network
$ docker network rm grid
The Hub and Nodes will be created on different machines/VMs, they need to know each other's IPs to communicate properly. If more than one node will be running on the same Machine/VM, they must be configured to expose different ports.
$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.26.0-20241101
$ docker run -d -p 5555:5555
--shm-size="2g"
-e SE_EVENT_BUS_HOST=<ip-from-machine-1>
-e SE_EVENT_BUS_PUBLISH_PORT=4442
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443
-e SE_NODE_HOST=<ip-from-machine-2>
selenium/node-chrome:4.26.0-20241101
$ docker run -d -p 5555:5555 `
--shm-size="2g" `
-e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
-e SE_EVENT_BUS_PUBLISH_PORT=4442 `
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 `
-e SE_NODE_HOST=<ip-from-machine-2> `
selenium/node-chrome:4.26.0-20241101
$ docker run -d -p 5555:5555
--shm-size="2g"
-e SE_EVENT_BUS_HOST=<ip-from-machine-1>
-e SE_EVENT_BUS_PUBLISH_PORT=4442
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443
-e SE_NODE_HOST=<ip-from-machine-3>
selenium/node-edge:4.26.0-20241101
$ docker run -d -p 5555:5555 `
--shm-size="2g" `
-e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
-e SE_EVENT_BUS_PUBLISH_PORT=4442 `
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 `
-e SE_NODE_HOST=<ip-from-machine-3> `
selenium/node-edge:4.26.0-20241101
$ docker run -d -p 5555:5555
--shm-size="2g"
-e SE_EVENT_BUS_HOST=<ip-from-machine-1>
-e SE_EVENT_BUS_PUBLISH_PORT=4442
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443
-e SE_NODE_HOST=<ip-from-machine-4>
selenium/node-firefox:4.26.0-20241101
$ docker run -d -p 5555:5555 `
--shm-size="2g" `
-e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
-e SE_EVENT_BUS_PUBLISH_PORT=4442 `
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 `
-e SE_NODE_HOST=<ip-from-machine-4> `
selenium/node-firefox:4.26.0-20241101
$ docker run -d -p 5556:5556
--shm-size="2g"
-e SE_EVENT_BUS_HOST=<ip-from-machine-1>
-e SE_EVENT_BUS_PUBLISH_PORT=4442
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443
-e SE_NODE_HOST=<ip-from-machine-4>
-e SE_NODE_PORT=5556
selenium/node-chrome:4.26.0-20241101
$ docker run -d -p 5556:5556 `
--shm-size="2g" `
-e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
-e SE_EVENT_BUS_PUBLISH_PORT=4442 `
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 `
-e SE_NODE_HOST=<ip-from-machine-4> `
-e SE_NODE_PORT=5556 `
selenium/node-chrome:4.26.0-20241101
Docker Compose is the simplest way to start a Grid. Use the linked resources below, save them locally and check the execution instructions on top of each file.
docker-compose-v2.yml
docker-compose-v3.yml
To stop the Grid and cleanup the created containers, run docker compose down
.
docker-compose-v3-swarm.yml
It is possible to start a Selenium Grid with all its components apart. For simplicity, only an example with docker compose will be provided. Save the file locally, and check the execution instructions on top of it.
docker-compose-v3-full-grid.yml
Environment variable | Option | Type | Default value | Description |
---|---|---|---|---|
SE_REJECT_UNSUPPORTED_CAPS |
--reject-unsupported-caps |
boolean | false |
Allow the Distributor to reject a request immediately if the Grid does not support the requested capability. |
SE_HEALTHCHECK_INTERVAL |
--healthcheck-interval |
int | 120 |
This ensures the server can ping all the Nodes successfully after an interval. |
Tests execution can be recorded by using the selenium/video:ffmpeg-7.1-20241101
Docker image. One container is needed per each container where a browser is running. This means if you are
running 5 Nodes/Standalone containers, you will need 5 video containers, the mapping is 1-1.
Currently, the only way to do this mapping is manually (either starting the containers manually or through
docker compose
). We are iterating on this process and probably this setup will be more simple in the future.
The video Docker image we provide is based on the ffmpeg Ubuntu image provided by the jrottenberg/ffmpeg project, thank you for providing this image and simplifying our work ?
From image tag based 4.20.0
onwards, the video Docker image is based on the FFmpeg Ubuntu image provided by
linuxserver/docker-ffmpeg project since the image is available for multi-platform.
Thank you for simplifying our project and helping us move forward with multiple architecture support.
Notes:
/videos
directory inside the video container. Map a local directory to get the videos.FILE_NAME
environment variable to avoid unexpected results.This example shows how to start the containers manually:
$ docker network create grid
$ docker run -d -p 4444:4444 -p 6900:5900 --net grid --name selenium --shm-size="2g" selenium/standalone-chrome:4.26.0-20241101
$ docker run -d --net grid --name video -v /tmp/videos:/videos selenium/video:ffmpeg-7.1-20241101
# Run your tests
$ docker stop video && docker rm video
$ docker stop selenium && docker rm selenium
After the containers are stopped and removed, you should see a video file on your machine's /tmp/videos
directory.
Here is an example using a Hub and a few Nodes:
docker-compose-v3-video.yml
Based on the support of Metadata in tests. When the video recorder is sidecar deployed with the browser node with enabling SE_VIDEO_FILE_NAME=auto
and adding metadata to your tests, video file name will extract value of capability se:name
and use it as the video file name.
For example in Python binding:
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium import webdriver
options = ChromeOptions()
options.set_capability('se:name', 'test_visit_basic_auth_secured_page (ChromeTests)')
driver = webdriver.Remote(options=options, command_executor="http://localhost:4444")
driver.get("https://selenium.dev")
driver.quit()
The output video file name will be test_visit_basic_auth_secured_page_ChromeTests_<sessionId>.mp4
.
If your test name is handled by the test framework, and it is unique for sure, you also can disable the session id appends to the video file name by setting SE_VIDEO_FILE_NAME_SUFFIX=false
.
File name will be trimmed to 255 characters to avoid long file names. Moreover, space
character will be replaced by _
and only characters alphabets, numbers, -
(hyphen), _
(underscore) are retained in the file name.
The trim regex is able to be customized by setting SE_VIDEO_FILE_NAME_TRIM_REGEX
environment variable. The default value is [:alnum:]-_
. The regex should be compatible with the tr
command in bash.
At deployment level, the recorder container is up always. In addition, you can disable video recording process via session capability se:recordVideo
. For example in Python binding:
options.set_capability('se:recordVideo', False)
In recorder container will perform query GraphQL in Hub based on Node SessionId and extract the value of se:recordVideo
in capabilities before deciding to start video recording process or not.
Notes: To reach the GraphQL endpoint, the recorder container needs to know the Hub URL. The Hub URL can be passed via environment variable SE_NODE_GRID_URL
. For example SE_NODE_GRID_URL
is http://selenium-hub:4444
.
RCLONE is installed in the video recorder image. You can use it to upload the videos to a cloud storage service. Besides the video recording mentioned above, you can enable the upload functionality by setting the following environment variables:
version: "3"
services:
chrome_video:
image: selenium/video:ffmpeg-7.1-20241101
depends_on:
- chrome
environment:
- DISPLAY_CONTAINER_NAME=chrome
- SE_VIDEO_FILE_NAME=auto
- SE_VIDEO_UPLOAD_ENABLED=true
- SE_UPLOAD_DESTINATION_PREFIX=s3://mybucket/path
- RCLONE_CONFIG_S3_TYPE=s3
- RCLONE_CONFIG_S3_PROVIDER=GCS
- RCLONE_CONFIG_S3_ENV_AUTH=true
- RCLONE_CONFIG_S3_REGION=asia-southeast1
- RCLONE_CONFIG_S3_LOCATION_CONSTRAINT=asia-southeast1
- RCLONE_CONFIG_S3_ACL=private
- RCLONE_CONFIG_S3_ACCESS_KEY_ID=xxx
- RCLONE_CONFIG_S3_SECRET_ACCESS_KEY=xxx
- RCLONE_CONFIG_S3_ENDPOINT=https://storage.googleapis.com
- RCLONE_CONFIG_S3_NO_CHECK_BUCKET=true
SE_VIDEO_FILE_NAME=auto
will use the session id as the video file name. This ensures that the video file name is unique to upload.
Video file name construction automatically works based on Node endpoint /status
(and optional GraphQL endpoint) to get session ID, capabilities.
SE_VIDEO_UPLOAD_ENABLED=true
will enable the video upload feature. In the background, it will create a pipefile with file and destination for uploader to consume and proceed.
SE_VIDEO_INTERNAL_UPLOAD=true
will use RCLONE installed in the container for upload. If you want to use another sidecar container for upload, set it to false
.
ENV variables per mode | Hub/Nodes | Standalone roles | Dynamic Grid |
---|---|---|---|
SE_VIDEO_RECORD_STANDALONE (mandatory) |
false (default) |
true |
true |
DISPLAY_CONTAINER_NAME (mandatory) |
user input | user input | (not required) |
SE_NODE_PORT (optional) |
5555 |
4444 |
(not required) |
SE_NODE_GRID_URL (optional) |
user input | (not required) | (not required) |
For environment variables with prefix RCLONE_
is used to pass remote configuration to RCLONE. You can find more information about RCLONE configuration here.
When using in Dynamic Grid, those variables should be combined with the prefix SE_
, for example SE_RCLONE_
. See below reference for more details.
Configure video recording and uploading for Hub and Nodes: docker-compose-v3-video-upload.yml
Configure video recording and uploading for Standalone roles: docker-compose-v3-video-upload-standalone.yml
Configure video recording and uploading for Dynamic Grid (node-docker): docker-compose-v3-video-upload-dynamic-grid.yml
Configure video recording and uploading for Dynamic Grid standalone (standalone-docker): tests/docker-compose-v3-test-standalone-docker.yaml
Environment variable | Default value | Description |
---|---|---|
SE_UPLOAD_RETAIN_LOCAL_FILE |
false |
Keep local file after uploading successfully |
SE_UPLOAD_COMMAND |
copy |
RCLONE command is used to transfer file. Enforce move when retain local file is false
|
SE_UPLOAD_OPTS |
-P --cutoff-mode SOFT --metadata --inplace |
Other options belong to RCLONE command can be set. |
SE_UPLOAD_CONFIG_FILE_NAME |
upload.conf |
Config file for remote host instead of set via env variable prefix SE_RCLONE_* |
SE_UPLOAD_CONFIG_DIRECTORY |
/opt/bin |
Directory of config file (change it when conf file in another directory is mounted) |
Grid 4 has the ability to start Docker containers on demand, this means that it starts a Docker container in the background for each new session request, the test gets executed there, and when the test completes, the container gets thrown away.
This execution mode can be used either in the Standalone or Node roles. The "dynamic"
execution mode needs to be told what Docker images to use when the containers get started.
Additionally, the Grid needs to know the URI of the Docker daemon. This configuration can
be placed in a local toml
file.
You can save this file locally and name it, for example, config.toml
.
[docker]
# Configs have a mapping between the Docker image to use and the capabilities that need to be matched to
# start a container with the given image.
configs = [
"selenium/standalone-firefox:4.26.0-20241101", '{"browserName": "firefox"}',
"selenium/standalone-chrome:4.26.0-20241101", '{"browserName": "chrome"}',
"selenium/standalone-edge:4.26.0-20241101", '{"browserName": "MicrosoftEdge"}'
]
host-config-keys = ["Dns", "DnsOptions", "DnsSearch", "ExtraHosts", "Binds"]
# URL for connecting to the docker daemon
# Most simple approach, leave it as http://127.0.0.1:2375, and mount /var/run/docker.sock.
# 127.0.0.1 is used because internally the container uses socat when /var/run/docker.sock is mounted
# If var/run/docker.sock is not mounted:
# Windows: make sure Docker Desktop exposes the daemon via tcp, and use http://host.docker.internal:2375.
# macOS: install socat and run the following command, socat -4 TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock,
# then use http://host.docker.internal:2375.
# Linux: varies from machine to machine, please mount /var/run/docker.sock. If this does not work, please create an issue.
url = "http://127.0.0.1:2375"
# Docker image used for video recording
video-image = "selenium/video:ffmpeg-7.1-20241101"
# Uncomment the following section if you are running the node on a separate VM
# Fill out the placeholders with appr