Problem
A script started with a Docker or Docker Compose interpreter in PyCharm opens a browser or another GUI application. No window appears on the host, and manual interaction with the page is not possible. Common cases are a Playwright or Selenium run in headed mode, and a matplotlib plot.
On Linux images the process often fails instead of opening a window, and the error names a missing display.
Cause
A container has no display server. A process started inside it that opens a window has nothing to render into.
The Docker interpreter integration runs processes in the container and streams their standard output and standard error. It does not forward window surfaces, so PyCharm has no display channel to expose. matplotlib doesn't work with remote docker interpreter records the same limitation for matplotlib.
Playwright documents the same constraint. Its continuous integration guide requires Xvfb and the xvfb-run wrapper to run headed browsers on Linux, described in Playwright's CI documentation.
Resolution
Three approaches avoid installing VNC inside the container. The right one depends on whether a live window is needed, and on where the dependencies may be installed.
Run the GUI part with a local interpreter
Select a local interpreter in the run configuration that opens the browser. The browser then opens as a normal window on the host and is fully interactive.
The service under test stays in the container and is reached over its published port, so the Compose file needs no change.
This approach installs the browser and its dependencies on the host as well as in the container.
Show the container's window on the host with an X server
Run an X server on the host, then pass a DISPLAY value to the service through the environment key in docker-compose.yml:
services:
app:
environment:
- DISPLAY=host.docker.internal:0.0
Nothing is installed inside the container, and only the X server is installed on the host. On Windows, the common X servers are VcXsrv, Xming, X410, and MobaXterm.
Two points decide whether the connection works:
- Configure the X server to accept incoming connections. It refuses them by default.
- Allow the X server through the host firewall.
host.docker.internal is the Docker Desktop name for the host machine. On a Linux host running Docker Engine without Docker Desktop, that name does not resolve. Debugging Django application with Docker Compose: No debug option or connection issues describes adding it through the extra_hosts key.
Because the X connection is unencrypted, use this approach on a trusted local machine rather than across a network.
Record the run instead of watching it
When the goal is to see what the page did rather than to click it, record a Playwright trace in the container:
context.tracing.start(screenshots=True, snapshots=True)
# ... the run ...
context.tracing.stop(path="trace.zip")
Open the file on the host with playwright show-trace trace.zip. The trace holds a DOM snapshot per action, described in Playwright's Trace viewer documentation. No display is needed anywhere.
Reuse a login session between the host and the container
A session saved as a storage state transfers between operating systems. browser_context.storage_state(path="state.json") writes a JSON file of cookies and local storage. The option also accepts a dictionary of cookie and origin data. Load the file in the container with browser.new_context(storage_state="state.json"). Both calls are described in Playwright's authentication documentation.
If the site keeps its token in IndexedDB, add indexed_db=True to the save call.
A persistent profile directory does not transfer. launch_persistent_context(user_data_dir=...) uses a real browser User Data Directory, defined as the parent of the profile path shown at chrome://version. That directory does not move between Windows and Linux. Use a storage state instead.
Some sites bind a session to the User-Agent, the IP address, or a device fingerprint. Such a site can reject a state captured on the host and replayed from the container. This is site behavior rather than a Playwright limitation. Where that happens, the X server approach is unaffected, because the login and the run both happen in the same container.
Comments
0 comments
Please sign in to leave a comment.