This issue from the microsoft/playwright-python
project appears to be related.
TL;DR: Since mkdocs-exporter
relies on playwright
and (as of 2024-06-20) it does not provide install instructions or a package for Alpine, without deep diving into what Alpine system-level dependencies are required (and if they are even available via official Alpine repos), there is no way to install mkdocs-exporter
into Alpine-based docker images. Those that attempt an install will receive playwright
related errors below. Unfortunately, the offical mkdocs-material
, is Alpine based at this time. So a supported theme (material) is only available to mkdocs-exporter
+mkdocs-material
users if they manually install mkdocs-material
and mkdocs-exporter
onto a playwright
supported OS (like Debian). This issue provides a sample Dockerfile that does exactly this and works as of 2024-06-20 with the current latest versions of mkdocs-material
, mkdocs-exporter
, and the playwright
Pypi packages; however, it would be great if mkdocs-exporter
developers could figure out how to allow for Alpine based installs or (at a mimimum) advertise that they do not support Alpine-based deployments.
Expected Behavior
Given I attempt to install mkdocs-exporter
into the official, latest docker.io/squidfunk/mkdocs-material:9.5.27
(v9.5.27 at the time of this bug report) Docker container image like so,
FROM docker.io/squidfunk/mkdocs-material:9.5.27
RUN pip install mkdocs-exporter
as described by the official mkdocs-material documentation for installing additional python plugin libraries,
When I execute a docker build
command, like so,
docker build -t mkdocs-material-with-exporter .
Then the Docker container image builds successfully and mkdocs-exporter
functions as described in the documentation when using it to export mkdocs sites as PDFs.
Observed Behavior
Given I attempt to install mkdocs-exporter
into the official, latest docker.io/squidfunk/mkdocs-material:9.5.27
(v9.5.27 at the time of this bug report) Docker container image like so,
FROM docker.io/squidfunk/mkdocs-material:9.5.27
RUN pip install mkdocs-exporter
as described by the official mkdocs-material documentation for installing additional python plugin libraries,
When I execute a docker build
command, like so,
docker build -t mkdocs-material-with-exporter .
Then the Docker container image fails to build, and provides the following error messages:
[+] Building 5.5s (6/6) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 117B 0.0s
=> [internal] load metadata for docker.io/squidfunk/mkdocs-material:9.5.27 0.5s
=> [auth] squidfunk/mkdocs-material:pull token for registry-1.docker.io 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [1/2] FROM docker.io/squidfunk/mkdocs-material:9.5.27@sha256:257eca88da7f42242cd05e8cebf6d10ebd079e 0.0s
=> ERROR [2/2] RUN pip install mkdocs-exporter 4.9s
------
> [2/2] RUN pip install mkdocs-exporter:
1.554 Collecting mkdocs-exporter
1.635 Downloading mkdocs_exporter-6.0.0-py3-none-any.whl.metadata (5.5 kB)
1.752 Collecting beautifulsoup4>=4.12.2 (from mkdocs-exporter)
1.766 Downloading beautifulsoup4-4.12.3-py3-none-any.whl.metadata (3.8 kB)
1.998 Collecting libsass>=0.22.0 (from mkdocs-exporter)
2.010 Downloading libsass-0.23.0.tar.gz (316 kB)
2.077 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ 316.1/316.1 kB 5.3 MB/s eta 0:00:00
2.119 Preparing metadata (setup.py): started
2.740 Preparing metadata (setup.py): finished with status 'done'
3.005 Collecting lxml>=4.9 (from mkdocs-exporter)
3.019 Downloading lxml-5.2.2-cp311-cp311-musllinux_1_2_x86_64.whl.metadata (3.4 kB)
3.028 Requirement already satisfied: mkdocs>=1.4 in /usr/local/lib/python3.11/site-packages (from mkdocs-exporter) (1.6.0)
3.114 INFO: pip is looking at multiple versions of mkdocs-exporter to determine which version is compatible with other requirements. This could take a while.
3.114 Collecting mkdocs-exporter
3.127 Downloading mkdocs_exporter-5.3.1-py3-none-any.whl.metadata (5.8 kB)
3.243 Collecting importlib-metadata>=6.0 (from mkdocs-exporter)
3.258 Downloading importlib_metadata-7.1.0-py3-none-any.whl.metadata (4.7 kB)
3.355 Collecting importlib-resources>=5.0 (from mkdocs-exporter)
3.367 Downloading importlib_resources-6.4.0-py3-none-any.whl.metadata (3.9 kB)
3.377 Requirement already satisfied: mkdocs-material<10.0.0,>=9.4.14 in /usr/local/lib/python3.11/site-packages (from mkdocs-material[imaging]<10.0.0,>=9.4.14->mkdocs-exporter) (9.5.27)
3.456 Collecting nest-asyncio>=1.5.6 (from mkdocs-exporter)
3.469 Downloading nest_asyncio-1.6.0-py3-none-any.whl.metadata (2.8 kB)
3.480 Collecting mkdocs-exporter
3.495 Downloading mkdocs_exporter-5.3.0-py3-none-any.whl.metadata (5.8 kB)
3.536 Downloading mkdocs_exporter-5.2.1-py3-none-any.whl.metadata (5.6 kB)
3.567 Downloading mkdocs_exporter-5.2.0-py3-none-any.whl.metadata (5.6 kB)
3.602 Downloading mkdocs_exporter-5.1.0-py3-none-any.whl.metadata (5.4 kB)
3.637 Downloading mkdocs_exporter-5.0.0-py3-none-any.whl.metadata (5.4 kB)
3.669 Downloading mkdocs_exporter-4.1.0-py3-none-any.whl.metadata (5.4 kB)
3.694 Collecting importlib-metadata<5.0 (from mkdocs-exporter)
3.706 Downloading importlib_metadata-4.13.0-py3-none-any.whl.metadata (4.9 kB)
3.717 INFO: pip is still looking at multiple versions of mkdocs-exporter to determine which version is compatible with other requirements. This could take a while.
3.718 Collecting mkdocs-exporter
3.731 Downloading mkdocs_exporter-4.0.2-py3-none-any.whl.metadata (5.4 kB)
3.766 Downloading mkdocs_exporter-4.0.1-py3-none-any.whl.metadata (5.4 kB)
3.809 Downloading mkdocs_exporter-4.0.0-py3-none-any.whl.metadata (5.4 kB)
3.846 Downloading mkdocs_exporter-3.1.1-py3-none-any.whl.metadata (5.4 kB)
3.881 Downloading mkdocs_exporter-3.1.0-py3-none-any.whl.metadata (5.4 kB)
3.899 INFO: This is taking longer than usual. You might need to provide the dependency resolver with stricter constraints to reduce runtime. See https://pip.pypa.io/warnings/backtracking for guidance. If you want to abort this run, press Ctrl + C.
3.915 Downloading mkdocs_exporter-3.0.3-py3-none-any.whl.metadata (5.4 kB)
3.956 Downloading mkdocs_exporter-3.0.2-py3-none-any.whl.metadata (5.4 kB)
3.993 Downloading mkdocs_exporter-3.0.1-py3-none-any.whl.metadata (5.4 kB)
4.034 Downloading mkdocs_exporter-3.0.0-py3-none-any.whl.metadata (5.4 kB)
4.079 Downloading mkdocs_exporter-2.0.2-py3-none-any.whl.metadata (5.4 kB)
4.122 Downloading mkdocs_exporter-2.0.1-py3-none-any.whl.metadata (4.7 kB)
4.168 Downloading mkdocs_exporter-2.0.0-py3-none-any.whl.metadata (4.6 kB)
4.197 Downloading mkdocs_exporter-1.3.0-py3-none-any.whl.metadata (4.7 kB)
4.216 Requirement already satisfied: mkdocs-material-extensions<2.0.0,>=1.1.1 in /usr/local/lib/python3.11/site-packages (from mkdocs-exporter) (1.3.1)
4.231 Downloading mkdocs_exporter-1.2.2-py3-none-any.whl.metadata (4.4 kB)
4.264 Downloading mkdocs_exporter-1.2.1-py3-none-any.whl.metadata (4.4 kB)
4.302 Downloading mkdocs_exporter-1.2.0-py3-none-any.whl.metadata (4.4 kB)
4.345 Downloading mkdocs_exporter-1.1.0-py3-none-any.whl.metadata (4.5 kB)
4.386 Downloading mkdocs_exporter-1.0.2-py3-none-any.whl.metadata (4.4 kB)
4.420 Downloading mkdocs_exporter-1.0.1-py3-none-any.whl.metadata (4.1 kB)
4.454 Downloading mkdocs_exporter-1.0.0-py3-none-any.whl.metadata (4.0 kB)
4.490 Downloading mkdocs_exporter-0.0.2-py3-none-any.whl.metadata (4.0 kB)
4.521 Downloading mkdocs_exporter-0.0.1-py3-none-any.whl.metadata (1.4 kB)
4.534 ERROR: Cannot install mkdocs-exporter==0.0.1, mkdocs-exporter==0.0.2, mkdocs-exporter==1.0.0, mkdocs-exporter==1.0.1, mkdocs-exporter==1.0.2, mkdocs-exporter==1.1.0, mkdocs-exporter==1.2.0, mkdocs-exporter==1.2.1, mkdocs-exporter==1.2.2, mkdocs-exporter==1.3.0, mkdocs-exporter==2.0.0, mkdocs-exporter==2.0.1, mkdocs-exporter==2.0.2, mkdocs-exporter==3.0.0, mkdocs-exporter==3.0.1, mkdocs-exporter==3.0.2, mkdocs-exporter==3.0.3, mkdocs-exporter==3.1.0, mkdocs-exporter==3.1.1, mkdocs-exporter==4.0.0, mkdocs-exporter==4.0.1, mkdocs-exporter==4.0.2, mkdocs-exporter==4.1.0, mkdocs-exporter==5.0.0, mkdocs-exporter==5.1.0, mkdocs-exporter==5.2.0, mkdocs-exporter==5.2.1, mkdocs-exporter==5.3.0, mkdocs-exporter==5.3.1 and mkdocs-exporter==6.0.0 because these package versions have conflicting dependencies.
4.534
4.534 The conflict is caused by:
4.534 mkdocs-exporter 6.0.0 depends on playwright>=1.33
4.534 mkdocs-exporter 5.3.1 depends on playwright>=1.33
4.534 mkdocs-exporter 5.3.0 depends on playwright>=1.33
4.534 mkdocs-exporter 5.2.1 depends on playwright>=1.33
4.534 mkdocs-exporter 5.2.0 depends on playwright>=1.33
4.534 mkdocs-exporter 5.1.0 depends on playwright>=1.33
4.534 mkdocs-exporter 5.0.0 depends on playwright>=1.33
4.534 mkdocs-exporter 4.1.0 depends on playwright>=1.33
4.534 mkdocs-exporter 4.0.2 depends on playwright>=1.33
4.534 mkdocs-exporter 4.0.1 depends on playwright>=1.33
4.534 mkdocs-exporter 4.0.0 depends on playwright>=1.33
4.534 mkdocs-exporter 3.1.1 depends on playwright>=1.33
4.534 mkdocs-exporter 3.1.0 depends on playwright>=1.33
4.534 mkdocs-exporter 3.0.3 depends on playwright>=1.33
4.534 mkdocs-exporter 3.0.2 depends on playwright>=1.33
4.534 mkdocs-exporter 3.0.1 depends on playwright>=1.33
4.534 mkdocs-exporter 3.0.0 depends on playwright>=1.33
4.534 mkdocs-exporter 2.0.2 depends on playwright>=1.33
4.534 mkdocs-exporter 2.0.1 depends on playwright>=1.33
4.534 mkdocs-exporter 2.0.0 depends on playwright>=1.33
4.534 mkdocs-exporter 1.3.0 depends on playwright>=1.33
4.534 mkdocs-exporter 1.2.2 depends on playwright>=1.33
4.534 mkdocs-exporter 1.2.1 depends on playwright>=1.33
4.534 mkdocs-exporter 1.2.0 depends on playwright>=1.33
4.534 mkdocs-exporter 1.1.0 depends on playwright>=1.33
4.534 mkdocs-exporter 1.0.2 depends on playwright>=1.33
4.534 mkdocs-exporter 1.0.1 depends on playwright>=1.33
4.534 mkdocs-exporter 1.0.0 depends on playwright>=1.33
4.534 mkdocs-exporter 0.0.2 depends on playwright>=1.33
4.534 mkdocs-exporter 0.0.1 depends on playwright>=1.33
4.534
4.534 To fix this you could try to:
4.534 1. loosen the range of package versions you've specified
4.534 2. remove package versions to allow pip attempt to solve the dependency conflict
4.534
4.535 ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts
------
Dockerfile:2
--------------------
1 | FROM docker.io/squidfunk/mkdocs-material:9.5.27
2 | >>> RUN pip install mkdocs-exporter
3 |
--------------------
ERROR: failed to solve: process "/bin/sh -c pip install mkdocs-exporter" did not complete successfully: exit code: 1
Additional Notes
Running pip --debug install mkdocs-exporter
on the RUN
line of the Dockerfile yields a more robust error message with colorized output. I have not provided that here due to the length of the output, the custom formatting that will likely get mangled, and how easily reproducible it is on a developer's local machine.
I have attempted this same install procedure with downgraded versions of both the Docker container image and the mkdocs-exporter
library, so I suspect it has been an issue for a while.
I have attempted explicitly installing playwright
via pip install playwright
inside the container and experienced similar errors.
$ docker run --rm -it --entrypoint '' docker.io/squidfunk/mkdocs-material:9.5.27 /bin/sh
/docs # pip install playwright
ERROR: Could not find a version that satisfies the requirement playwright (from versions: none)
ERROR: No matching distribution found for playwright
Attempting to install older versions of playwright explicitly (playwright==1.33.0
, for example) yields the same results.
The docker.io/squidfunk/mkdocs-material:9.5.27
image uses Alpine 3.19.1, which is still supported by the Alpine team until 2025-05-09.
It looks like playwright
is not installable on the upstream vanilla Alpine image either based on this test:
$ docker run --rm -it --entrypoint '' docker.io/alpine:3.19.1 /bin/sh
# apk add python3
# apk add py3-pip
# pip install --break-system-packages playwright
However, it has no issues on this Debian-based image:
$ docker run --rm -it --entrypoint '' docker.io/python:3-bookworm /bin/sh
# pip install playwright
I was able to get mkdocs-exporter
working by translating the official mkdocs-material
Dockerfile to a functionally equivalent Debian-based one, but that solution is not exactly ideal. For anyone else trying to solve this same issue in the interim, here is the Dockerfile:
FROM python:3.11-bookworm
# Build-time flags
ARG WITH_PLUGINS=true
# Environment variables
ENV PACKAGES=/usr/local/lib/python3.11/site-packages
ENV PYTHONDONTWRITEBYTECODE=1
# Set build directory
WORKDIR /tmp
# Copy files necessary for build
COPY mkdocs-material/material material
COPY mkdocs-material/package.json package.json
COPY mkdocs-material/README.md README.md
COPY mkdocs-material/*requirements.txt ./
COPY *requirements.txt ./
COPY mkdocs-material/pyproject.toml pyproject.toml
# Perform build and cleanup artifacts and caches
RUN \
apt update \
&& \
apt install -y \
libcairo2-dev \
libfreetype-dev \
git \
libjpeg-dev \
openssh-client \
tini \
zlib1g-dev \
&& \
apt install -v \
gcc \
libffi-dev \
&& \
pip install --no-cache-dir --upgrade pip \
&& \
if [ "${WITH_PLUGINS}" = "true" ]; then \
pip install --no-cache-dir \
mkdocs-material[recommended] \
mkdocs-material[imaging] \
mkdocs-exporter \
mkdocs-macros-plugin; \
fi \
&& \
for theme in mkdocs readthedocs; do \
rm -rf ${PACKAGES}/mkdocs/themes/$theme; \
ln -s \
${PACKAGES}/material/templates \
${PACKAGES}/mkdocs/themes/$theme; \
done \
&& \
playwright install \
&& \
playwright install-deps \
&& \
find ${PACKAGES} \
-type f \
-path "*/__pycache__/*" \
-exec rm -f {} \; \
&& \
git config --system --add safe.directory /docs \
&& \
git config --system --add safe.directory /site
# Set working directory
WORKDIR /docs
# Expose MkDocs development server port
EXPOSE 8000
# Start development server by default
ENTRYPOINT ["/usr/bin/tini", "--", "mkdocs"]
CMD ["serve", "--dev-addr=0.0.0.0:8000"]
Note: size-wise, this is nowhere as close to as slim as the Alpine-based image provided by squidfunk/mkdocs-material
, and I am sure there is more refinement that can be done to make it slimmer, but it works (as of v9.5.27 of mkdocs-material). Here is the original Dockerfile that this one is based on. This Dockerfile assumes that you have done a git clone
of squidfunk/mkdocs-material
from Github and that repository is in a subdirectory relative to this Dockerfile.
The biggest differences between this Dockerfile and the official one from mkdocs-material are:
- Debian vs Alpine based, so FROM line is different and
apt
is used instead of apk
for system pkg installs
- Equivalent package names are different (some are not required) on Debian vs Alpine
tini
is installed in a different directory so the ENTRYPOINT is different
- Cannot remove the .cache directory because this is where PDFs are cached post-build
- Removed the
user-requirements.txt
install lines and hardcoded the install of libraries like mkdocs-exporter
- Not clearing the package manager cache or removing build deps after system pkg installs