Today, just a quick article about how to run X Apss on Mac using Docker. Why? While it cannot be considered a sandbox, it can be considered a quick solution between running something in our system and running something inside a virtual machine. Again, why? Let’s say we want to open a PDF, we have to check it with VirusTotal, and while it looks like an innocuous file, it has some YARA rules warning and we do not want to take any risk. We can run a PDF viewer inside a container.
To do this we are going to need a few things:
- XQuartz is easily installable with Homebrew.
- Docker, the are multiple ways to install it. Homebrew or the Docker Desktop app seem the easiest ones.
That is all the pre-requirements we need. Once we have them installed, we can proceed to create our container.
In this case, I am going to use an Ubuntu container and I am going to install the Evince Document Viewer, but the steps should work for any flavour of the container you like and any document viewer you prefer. And, for any X App, we want.
First, we need to create our Dockerfile:
# Use a Linux base image
FROM ubuntu:latest
# Install necessary packages
RUN apt-get update && apt-get install -y \
evince \
x11-apps
# Set the display environment variable
ENV DISPLAY=:0
# Create a non-root user
RUN groupadd -g 1000 myuser && useradd -u 1000 -g myuser -s /bin/bash -m myuser
# Copy the entrypoint script
COPY entrypoint.sh /
# Set the entrypoint script as executable
RUN chmod +x /entrypoint.sh
# Switch to the non-root user
USER myuser
# Set the entrypoint
ENTRYPOINT ["/entrypoint.sh"]
Second, we need the entry point file to execute our app and pass the argument, in this case, the file we want to open:
#!/bin/bash
evince "$1"
Now, we can build our container by executing the proper docker command in the folder that contains both files:
docker build -t pdf-viewer .
Now, we just need to run it:
- Ensure docker is running in our system.
- Start the XQuartz application.
- Execute
xhost +localhost
, this command grants permission for the Docker container to access the X server display. - Run our container with the following command:
docker run --rm -it \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /Users/username/pdf-location:/data \
--entrypoint /entrypoint.sh pdf-viewer /data/file.pdf
Let’s elaborate on the command a bit:
docker run
: This command is used to run a Docker container.--rm
: This flag specifies that the container should be automatically removed once it exits. This helps keep the system clean by removing the container after it finishes execution.-it
: These options allocate a pseudo-TTY and enable interactive mode, allowing you to interact with the container.-e DISPLAY=$DISPLAY
: This option sets theDISPLAY
environment variable in the container to the value of theDISPLAY
variable on your local machine. It enables the container to connect to the X server display.-v /tmp/.X11-unix:/tmp/.X11-unix
: This option mounts the X server socket directory (/tmp/.X11-unix
) from your local machine to the same path (/tmp/.X11-unix
) within the container. It allows the container to access the X server for display forwarding.-v /Users/username/pdf-location:/data
: This option mounts the/Users/username/pdf-location
directory on your local machine to the/data
directory within the container. It provides access to the PDF file located at/Users/username/pdf-location
inside the container.--entrypoint /entrypoint.sh
: This option sets the entry point for the container to/entrypoint.sh
, which is a script that will be executed when the container starts.pdf-viewer
: This is the name of the Docker image you want to run the container from./data/file.pdf
: This specifies the path to the PDF file inside the container that you want to open with the PDF viewer.
With this, we are already done. Executing this command the PDF Document Viewer will open with our PDF. Happy reading!
There is one extra and optional step we can take, it is to create an alias to facilitate the execution:
alias run-pdf-viewer='function _pdf_viewer() { xhost +localhost >/dev/null 2>&1;docker run -it --rm --env="DISPLAY=host.docker.internal:0" -v $1:/data --entrypoint /entrypoint.sh pdf-viewer /data/$2 };_pdf_viewer'
The above alias allows us to open a PDF file inside the container without remembering the more complex commands, we only need to ensure Docker is running. As an example, we can open a file with:
run-pdf-viewer ~/Downloads example.pdf