microsoft / playwright-dotnet

.NET version of the Playwright testing and automation library.
https://playwright.dev/dotnet/
MIT License
2.48k stars 235 forks source link

Docker: How to build a functional Dockerfile #982

Closed pablopioli closed 3 years ago

pablopioli commented 3 years ago

I'm trying to understand how to run PlaywrightSharp in a docker container. I started with the basic, the Net Core image and got:

PlaywrightSharp.PlaywrightSharpException: 'Host system is missing dependencies!

  Missing libraries are:
      libgobject-2.0.so.0
      libglib-2.0.so.0
      libnss3.so
      libnssutil3.so
      libsmime3.so
      libnspr4.so
      libatk-1.0.so.0
      libatk-bridge-2.0.so.0
      libx11.so.6
      libx11-xcb.so.1
      libxcb.so.1
      libcups.so.2
      libdbus-1.so.3
      libgio-2.0.so.0
      libexpat.so.1
      libdrm.so.2
      libxkbcommon.so.0
      libxcomposite.so.1
      libxdamage.so.1
      libxext.so.6
      libxfixes.so.3
      libxrandr.so.2
      libgtk-3.so.0
      libgdk-3.so.0
      libpango-1.0.so.0
      libcairo.so.2
      libgdk_pixbuf-2.0.so.0
      libgbm.so.1
      libasound.so.2
      libatspi.so.0

I know documentation on this topic is missing, but I would like wich is the best way to start:

Option A: The Playwright image and install Net Core dependencies Option B: The Net Core image and install Playwright dependencies

I took a look at the Dockerfile from the Playwright project but could not make it work.

kblok commented 3 years ago

Opcion C :) : Create an image starting from the playwright one and install .NET Core there.

https://playwright.dev/#version=v1.5.2&path=docs%2Fdocker%2FREADME.md&q=

pablopioli commented 3 years ago

So I ended with this Dockerfile

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as build
WORKDIR /src
COPY ["MyApp.csproj", ""]
RUN dotnet restore "./MyApp.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet publish "MyApp.csproj" -c Release -o /publish

FROM mcr.microsoft.com/playwright:focal AS playwright
RUN apt-get install -y wget
RUN wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt-get update; \
         apt-get install -y apt-transport-https && \
         apt-get update && \
         apt-get install -y aspnetcore-runtime-3.1
RUN apt-get remove -y wget
RUN groupadd -r pwuser && useradd -r -g pwuser -G audio,video pwuser \
    && mkdir -p /home/pwuser/Downloads \
    && chown -R pwuser:pwuser /home/pwuser \
    && mkdir -p /app \
    && chown -R pwuser:pwuser /app
COPY --from=build /publish /app
ENTRYPOINT ["dotnet", "/app/MyApp.dll"]

that I run with

docker run --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json myimage

Anyone see a security flaw or something on it?

If it's safe I can build a PR documenting it so others can use it.

jacobneroth commented 3 years ago

Can this be added to the Sample, would be helpful for everyone ? Spent a good day on this. :) Still getting the same dependencies missing exception. @kblok : Can this be another docker file ? , seems like it is an issue while downloading updates via the cooporate network.

pablopioli commented 3 years ago

The problem is the combination of versions, of Playwright and .Net.

This Dockerfile is for Net Core 3.1, I have built a new one for Net 5. And you need to match the version of the Playwright image you have used with the Nuget packaged used.

I see it more like a template that you adapt to your specific needs.

jacobneroth commented 3 years ago

Thanks pablopioli, any chance you can share that the one with .net 5 ? It does look like my company proxy is not allowing me to Run RUN apt-get install -y wget , even with the proxies. Sigh!

mobstation commented 3 years ago

We had some issues where it the .net playwright was looking for the chromium version chromium-827102 but what was actually downloaded in the container based on mcr.microsoft.com/playwright:focal was chromium-833159.

We "solved" this by added a step in our docker container that copied the browser downloaded from the .net build step to the resulting container keeping them in sync.

WORKDIR /root/.cache/ms-playwright
COPY --chown=pwuser:pwuser --from=build /root/.cache/ms-playwright ./

Feels slightly iffy but we couldn't see a way to solve it in another way. Anyone can point in a better direction?

Our complete docker file for context:

WORKDIR /app

COPY *.csproj nuget.config ./
RUN dotnet restore

COPY /. ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/playwright:focal AS playwright
RUN apt-get install -y wget
RUN wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt-get update; \
    apt-get install -y apt-transport-https && \
    apt-get update && \
    apt-get install -y aspnetcore-runtime-3.1
RUN apt-get remove -y wget

WORKDIR /root/.cache/ms-playwright
COPY --chown=pwuser:pwuser --from=build /root/.cache/ms-playwright ./

WORKDIR /app
COPY --from=build /app/out ./

ENV ASPNETCORE_URLS=http://+:80
ENV DOTNET_RUNNING_IN_CONTAINER=true
ENTRYPOINT ["dotnet", "app.dll"]
kblok commented 3 years ago

@mobstation you should keep versions in sync. So if you use pw# 0.162.0 you should do FROM mcr.microsoft.com/playwright:v1.6.2-focal

Another thing here @pablopioli, @jacobneroth. pw# seems to be working on .NET, BUT we have one outstanding bug due to a breaking change in System.Text.Json https://github.com/dotnet/runtime/issues/45833

mobstation commented 3 years ago

@kblok Ah right, that makes total sense. Thanks a lot for your help!

pablopioli commented 3 years ago

Since (I guess) 0.152.0 the playwright user is already present in the Playwright image, the previous recipe does not apply anymore.

It should be

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as build
WORKDIR /src
COPY ["MyApp.csproj", ""]
RUN dotnet restore "./MyApp.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet publish "MyApp.csproj" -c Release -o /publish

FROM mcr.microsoft.com/playwright:v1.6.2-focal AS playwright
RUN apt-get install -y wget
RUN wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt-get update; \
         apt-get install -y apt-transport-https && \
         apt-get update && \
         apt-get install -y aspnetcore-runtime-3.1
RUN apt-get remove -y wget
RUN mkdir -p /app \
    && chown -R pwuser:pwuser /app
COPY --from=build /publish /app
ENTRYPOINT ["dotnet", "/app/MyApp.dll"]

The recipe still targets Playwright 1.6.2 and Net Core 3.1. The sample app I use to test it breaks on newer versions of Playwright so can't use it. Maybe because of https://github.com/dotnet/runtime/issues/45833 ?

Will need more time to investigate.

pablopioli commented 3 years ago

And this is for Playwright 0.191 on Net 5. It´s a little different since the platform runtimes are copied at build time.

FROM mcr.microsoft.com/dotnet/sdk:5.0 as build
WORKDIR /src
COPY ["MyApp.csproj", ""]
RUN dotnet restore "./MyApp.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet publish /src/MyApp/MyApp.csproj -c Release -o /publish \
    && mkdir /publish/.playwright \
    && cp -r /src/MyApp/bin/Release/net5.0/.playwright/unix /publish/.playwright 

FROM mcr.microsoft.com/playwright:v1.9.1-focal AS playwright
RUN apt-get update \
    && apt-get install -y wget \
    && wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
    && dpkg -i packages-microsoft-prod.deb \
    && apt-get update \
    && apt-get install -y apt-transport-https \
    && apt-get install -y aspnetcore-runtime-5.0 \
    && apt-get remove -y wget
EXPOSE 80
COPY --from=build /publish/ /app/
RUN chown -R pwuser:pwuser /app
ENTRYPOINT ["dotnet", "/app/MyApp.dll"]
pablopioli commented 3 years ago

Currently you need to tinker the image a little if you need to use the restful mode, since there is a bug in PlaywrightSharp.

See https://github.com/microsoft/playwright-sharp/issues/1271 for a workaround.

GaryYu2by2 commented 3 years ago

Our client only allows Debian images in their k8s, they require a gRPC service to capture PDFs from one of their in-house developed web app. This is the complete Docker file, works with both asp.net core 3.1 and 5.0. For Playwright 0.162.0 and Chromium only.

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base

RUN apt-get update && apt-get install -y --no-install-recommends \
    xvfb

RUN apt-get update && apt-get install -y --no-install-recommends \
    fonts-liberation\
    libasound2\
    libatk-bridge2.0-0\
    libatk1.0-0\
    libatspi2.0-0\
    libcairo2\
    libcups2\
    libdbus-1-3\
    libdrm2\
    libgbm1\
    libglib2.0-0\
    libgtk-3-0\
    libnspr4\
    libnss3\
    libpango-1.0-0\
    libx11-6\
    libxcb1\
    libxcomposite1\
    libxdamage1\
    libxext6\
    libxfixes3\
    libxrandr2

 RUN apt-get update && apt-get install -y npm && \
     npm i playwright-chromium@1.6.2 && \
     npm i playwright-firefox@1.6.2 && \
     npm i playwright-webkit@1.6.2
 RUN apt-get remove nodejs -y

WORKDIR /app
EXPOSE 80

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

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

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]
pavelfeldman commented 3 years ago

Closing this as a part of the triage - it does not look actionable on our side. Please file new issues for outstanding problems!

VBoB13 commented 2 years ago

Opcion C :) : Create an image starting from the playwright one and install .NET Core there.

https://playwright.dev/#version=v1.5.2&path=docs%2Fdocker%2FREADME.md&q=

Isn't that Option B? :P Jokes aside - I have the very same issue but with Apache Airflow + Playwright... Any ideas as to which way would be best for that combo? (Beginner at Docker & Airflow)

mxschmitt commented 2 years ago

Opcion C :) : Create an image starting from the playwright one and install .NET Core there.

https://playwright.dev/#version=v1.5.2&path=docs%2Fdocker%2FREADME.md&q=

Isn't that Option B? :P Jokes aside - I have the very same issue but with Apache Airflow + Playwright... Any ideas as to which way would be best for that combo? (Beginner at Docker & Airflow)

There is now an official image: https://playwright.dev/dotnet/docs/docker

michael-freidgeim-webjet commented 1 year ago

@pavelfeldman > Closing this as a part of the triage - it does not look actionable on our side.

Can this be added to the Sample, would be helpful for everyone ?