This scenario might be useful to anyone who is willing to write some browser automation or run integration tests with Selenium in .NET Core application in a headless mode in docker.

Simple .NET Application with Selenium, Firefox and GeckoDriver

Let's start with a simple .NET Core application. I am using .NET 5.0 but this should work with any "core" version of the .NET Framework.

using var browser = new FirefoxDriver();
browser.Go("https://youtube.com/");
// some other browser related logic here
browser.Quit();

You also have to add Selenium.WebDriver.GeckoDriver and Selenium.WebDriver nuget packages to the project.

Also you have to let the project know that it should copy geckodriver to the publish folder. Add this to the csproj file:

<ItemGroup>
   <Content Include="$(TargetDir)\geckodriver" CopyToPublishDirectory="Always">
      <Link>geckodriver</Link>
   </Content>
</ItemGroup>

Now you can run it locally and see that everything is working as expected.

Add Docker Support to .NET Application

Now you have to create Dockerfile in the project folder with the following content (remember to replace project name):

FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
RUN apt-get update
RUN apt-get install -y xvfb
RUN echo "deb http://deb.debian.org/debian/ unstable main contrib non-free" >> /etc/apt/sources.list.d/debian.list
RUN apt-get update
RUN apt-get install -y libcrypt1
RUN apt-get install -y firefox
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["Folder/Project.csproj", "Folder/"]
RUN dotnet restore "Folder/Project.csproj"
COPY . .
WORKDIR "/src/Folder"
RUN dotnet build "Project.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Project.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["/bin/sh", "-c", "/usr/bin/xvfb-run -a $@", ""]
CMD ["dotnet", "Project.dll"]

This is a slightly modified version of the standard Dockerfile generated by Visual Studio.

Let's see what is the difference.

Install xvfb and Firefox in dotnet/runtime docker image

To install xvfb (here you can see what this is) you first have to run `apt-get update` and the install the package:

RUN apt-get update 
RUN apt-get install -y xvfb

Next, you have to add unstable package repo, since Debian (Microsoft uses Debian bustre-slim as a base image for `dotnet/runtime` image and it only contains firefox-esr but it is really unstable with the latest Firefox versions and I couldn't run my automation with it. So here is how you install firefox in yur docker image:

RUN echo "deb http://deb.debian.org/debian/ unstable main contrib non-free" >> /etc/apt/sources.list.d/debian.list 
RUN apt-get update 
RUN apt-get install -y libcrypt1 
RUN apt-get install -y firefox

The other tricky part is how to run xvfb-run command in a docker container. By default it will not work and will block executon of your code so you have to use this combination of ENTRYPOINT and CMD:

ENTRYPOINT ["/bin/sh", "-c", "/usr/bin/xvfb-run -a $@", ""] 
CMD ["dotnet", "Project.dll"]

Run xvfb with Firefox in Docker

Time to build your image:

docker build -t name -f .\Dockerfile .

and run it:

docker run -it --rm name

I hope it worked and now you can run your selenium tests or automation in a headless mode in docker.