Skip to content

Commit 660ef53

Browse files
authored
Dockerfile: use a shell script to create a host UID/GID-based container user (#27)
1 parent 977d854 commit 660ef53

File tree

3 files changed

+66
-15
lines changed

3 files changed

+66
-15
lines changed

Dockerfile

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ FROM ubuntu:24.04
44
RUN apt-get update && apt-get install -y \
55
curl \
66
git \
7+
gosu \
78
python3 \
89
python3-pip \
910
python3-venv \
@@ -18,15 +19,6 @@ RUN wget -q -O google-chrome.deb https://dl.google.com/linux/direct/google-chrom
1819
&& apt-get install -y ./google-chrome.deb \
1920
&& rm google-chrome.deb
2021

21-
# Create a new non-root user and group.
22-
# NOTE: It is important that a non-root user is used because otherwise the
23-
# Chrome Driver fails with: "User data directory is already in use"
24-
# https://github.com/SeleniumHQ/selenium/issues/15327#issuecomment-2688613182
25-
RUN groupadd -r html2print && useradd -r -m -g html2print html2print
26-
27-
# Grant the new user sudo privileges.
28-
RUN echo "html2print ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/html2print
29-
3022
# Create a virtual environment in the user's home directory.
3123
RUN python3 -m venv /opt/venv
3224

@@ -47,9 +39,14 @@ RUN if [ "$HTML2PRINT_SOURCE" = "pypi" ]; then \
4739
fi; \
4840
chmod -R 777 /opt/venv;
4941

50-
USER html2print
42+
# Remove the default 'ubuntu' user.
43+
RUN userdel -r ubuntu 2>/dev/null || true
44+
45+
# Allow updating the UID/GID dynamically at runtime
46+
COPY entrypoint.sh /entrypoint.sh
47+
RUN chmod +x /entrypoint.sh
5148

5249
# Set the working directory to the user's home directory.
5350
WORKDIR /data
5451

55-
ENTRYPOINT ["/bin/bash"]
52+
ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/sh
2+
3+
# This custom entrypoint script is needed for creating a container user with
4+
# a host's UID/GUI which enables sharing of the files between the container
5+
# and the host.
6+
# NOTE: It is important that a non-root user is used because otherwise the
7+
# Chrome Driver fails with: "User data directory is already in use"
8+
# https://github.com/SeleniumHQ/selenium/issues/15327#issuecomment-2688613182
9+
10+
set -e
11+
12+
# Ensure we have the environment variables
13+
if [ -z "$HOST_UID" ] || [ -z "$HOST_GID" ]; then
14+
echo "HOST_UID and HOST_GID must be set!"
15+
exit 1
16+
fi
17+
18+
echo "html2print/docker: running a Docker container entrypoint."
19+
echo "html2print/docker: ensuring html2print user with UID=$HOST_UID and GID=$HOST_GID exists"
20+
21+
# Check if a user with this UID already exists (e.g., "ubuntu")
22+
EXISTING_USER=$(getent passwd "$HOST_UID" | cut -d: -f1)
23+
24+
if [ -n "$EXISTING_USER" ]; then
25+
echo "error: html2print/docker: detected a wrong user: '$EXISTING_USER'. Ensure that any default users are removed from the Dockerfile. This entrypoint script is supposed to create a new user 'html2print'."
26+
exit 1
27+
else
28+
# Ensure the group exists.
29+
EXISTING_GROUP=$(getent group "$HOST_GID" | cut -d: -f1)
30+
if [ -z "$EXISTING_GROUP" ]; then
31+
echo "html2print/docker: creating new group html2print with GID=$HOST_GID"
32+
groupadd -g "$HOST_GID" html2print
33+
else
34+
echo "html2print/docker: group with GID=$HOST_GID already exists: $EXISTING_GROUP, reusing it."
35+
fi
36+
37+
# Create the user.
38+
echo "html2print/docker: creating new user html2print with UID=$HOST_UID"
39+
useradd -m -u "$HOST_UID" -g "$HOST_GID" -s /bin/bash html2print
40+
41+
# Give the user root privileges. Useful for debugging.
42+
echo "html2print ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/html2print
43+
fi
44+
45+
echo "html2print/docker: show created user info:"
46+
id html2print
47+
48+
# Run as the correct user. If no command is provided, run a shell.
49+
if [ $# -eq 0 ]; then
50+
echo "html2print/docker: no command provided, opening an interactive shell."
51+
exec gosu html2print /bin/bash
52+
else
53+
# Otherwise, run the provided command.
54+
exec gosu html2print "$@"
55+
fi

tasks.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,6 @@ def run_docker(
296296
command_argument = (
297297
f'/bin/bash -c "{command}"' if command is not None else ""
298298
)
299-
entry_point_argument = '--entrypoint=""' if command_argument else ""
300299

301300
run_invoke(
302301
context,
@@ -305,8 +304,8 @@ def run_docker(
305304
--name html2print
306305
--rm
307306
-it
308-
-v "$(pwd):/data"
309-
{entry_point_argument}
307+
-e HOST_UID=$(id -u) -e HOST_GID=$(id -g)
308+
-v "$(pwd):/data:rw"
310309
{image}
311310
{command_argument}
312311
""",
@@ -326,6 +325,6 @@ def test_docker(context, image: str = "html2print:latest"):
326325
context,
327326
image=image,
328327
command=(
329-
"cd tests/integration/01_hello_world && html2print print --debug index.html /data/output/index.pdf && cat /tmp/chromedriver.log"
328+
"cd tests/integration/01_hello_world && html2print print index.html /data/output/index.pdf"
330329
),
331330
)

0 commit comments

Comments
 (0)