Skip to content

Commit 971861e

Browse files
authored
Add option to set UID & GID env vars (#102)
1 parent ac7f429 commit 971861e

File tree

7 files changed

+127
-3
lines changed

7 files changed

+127
-3
lines changed

docker/Dockerfile

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,43 @@
66
# --
77
# Upstream images
88

9-
FROM alpine:3.19 AS alpine_upstream
109
FROM python:3.11-slim AS python_upstream
1110

1211

12+
# --
13+
# Python + Docker image
14+
15+
FROM python_upstream AS python_docker
16+
17+
# Install Docker CLI
18+
RUN --mount=type=cache,target=/var/cache/apt \
19+
--mount=type=cache,target=/var/lib/apt \
20+
apt-get update && \
21+
apt-get install -y \
22+
ca-certificates \
23+
curl \
24+
&& \
25+
install -m 0755 -d /etc/apt/keyrings && \
26+
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \
27+
chmod a+r /etc/apt/keyrings/docker.asc && \
28+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
29+
https://download.docker.com/linux/debian \
30+
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
31+
tee /etc/apt/sources.list.d/docker.list > /dev/null \
32+
&& \
33+
apt-get update && \
34+
apt-get install -y \
35+
docker-ce \
36+
docker-ce-cli \
37+
containerd.io \
38+
docker-buildx-plugin \
39+
docker-compose-plugin
40+
41+
1342
# --
1443
# Base image
1544

16-
FROM python_upstream AS app_base
45+
FROM python_docker AS app_base
1746

1847
# Set app directory
1948
WORKDIR /app

dockerc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ while true; do
5050
shift
5151
;;
5252

53+
'--uid' | '-u' )
54+
# Set user & group id environment variable
55+
DOCKERC_UID='true'
56+
shift
57+
;;
58+
5359
'--update' )
5460
# Update DockerC
5561
DOCKERC_UPDATE='true'
@@ -199,6 +205,7 @@ if [ "$DOCKERC_DEBUG_ARGS" = 'true' ]; then
199205
echo "DOCKERC_FORCE: $DOCKERC_FORCE"
200206
echo "DOCKERC_DRY_RUN: $DOCKERC_DRY_RUN"
201207
echo "DOCKERC_QUIET: $DOCKERC_QUIET"
208+
echo "DOCKERC_UID: $DOCKERC_UID"
202209
echo "DOCKERC_UPDATE: $DOCKERC_UPDATE"
203210
echo "DOCKERC_INSTALL_DIR: $DOCKERC_INSTALL_DIR"
204211
echo "DOCKERC_CONTEXT: $DOCKERC_CONTEXT"
@@ -225,6 +232,12 @@ if [ -n "$DOCKERC_QUIET" ]; then
225232
QUIET="$DOCKERC_QUIET"
226233
fi
227234

235+
SET_UID='false'
236+
if [ -n "$DOCKERC_UID" ]; then
237+
# Use from argument or environment variable
238+
SET_UID="$DOCKERC_UID"
239+
fi
240+
228241
UPDATE='false'
229242
if [ -n "$DOCKERC_UPDATE" ]; then
230243
# Use from argument or environment variable
@@ -547,6 +560,12 @@ if [ "$UPDATE" = 'true' ]; then
547560
exit ${ERROR_CODE:-0}
548561
fi
549562

563+
# Set user & group id environment variable
564+
if [ "$SET_UID" = 'true' ]; then
565+
export UID="$(id -u)"
566+
export GID="$(id -g)"
567+
fi
568+
550569
# Handle docker presets
551570
if [ -n "$DOCKER_PRESET" ]; then
552571

test/src/RunDockerc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def __init__(
99
cwd: str,
1010
context: str | None = None,
1111
env: dict[str, str] | None = None,
12+
dry_run: bool = True,
1213
):
1314
self.dockerc_path = dockerc_path
1415
self.dockerc_args = dockerc_args
@@ -21,11 +22,12 @@ def __init__(
2122
None
2223
)
2324
self.env = env
25+
self.dry_run = dry_run
2426

2527
self.proc = subprocess.Popen(
2628
[
2729
self.dockerc_path,
28-
'-n',
30+
*(['-n'] if self.dry_run else []),
2931
*self.dockerc_args,
3032
],
3133
cwd = self.cwd,

test/src/TestDirContext.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ def run_dockerc(
2929
*args: list[str],
3030
cwd: str | None = None,
3131
env: dict[str, str] | None = None,
32+
dry_run: bool = True,
3233
) -> RunDockerc:
3334
return RunDockerc(
3435
self.dockerc_path,
3536
dockerc_args = args,
3637
cwd = cwd or self.cwd,
3738
env = env,
39+
dry_run = dry_run,
3840
)

test/test/uid/__init__.py

Whitespace-only changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
services:
2+
app:
3+
image: app:latest
4+
user: ${UID:-1001}

test/test/uid/test_uid.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from test.src.format_dockerc_stdout import format_dockerc_stdout
2+
from test.src.TestDirContext import TestDirContext
3+
4+
def test_dry_run(file = __file__):
5+
with TestDirContext(file) as ctx:
6+
dockerc = ctx.run_dockerc(
7+
'base', 'config',
8+
)
9+
dockerc.assert_context_ok(
10+
format_dockerc_stdout(
11+
b'docker compose'
12+
b' -f ./docker-compose-base.yml'
13+
b' config'
14+
),
15+
)
16+
17+
def test_no_uid(file = __file__):
18+
with TestDirContext(file) as ctx:
19+
dockerc = ctx.run_dockerc(
20+
'base', 'config',
21+
dry_run = False,
22+
)
23+
dockerc.assert_context_ok(
24+
format_dockerc_stdout(
25+
b'docker compose'
26+
b' -f ./docker-compose-base.yml'
27+
b' config'
28+
) +
29+
b'name: cwd\n'
30+
b'services:\n'
31+
b' app:\n'
32+
b' image: app:latest\n'
33+
b' networks:\n'
34+
b' default: null\n'
35+
b' user: "1001"\n'
36+
b'networks:\n'
37+
b' default:\n'
38+
b' name: cwd_default\n'
39+
)
40+
41+
def test_uid_shell(shell):
42+
ret = shell.run("sh", "-c", "exit $(id -u)")
43+
assert ret.returncode == 0
44+
45+
def test_uid(file = __file__):
46+
with TestDirContext(file) as ctx:
47+
dockerc = ctx.run_dockerc(
48+
'-u',
49+
'base', 'config',
50+
dry_run = False,
51+
)
52+
dockerc.assert_context_ok(
53+
format_dockerc_stdout(
54+
b'docker compose'
55+
b' -f ./docker-compose-base.yml'
56+
b' config'
57+
) +
58+
b'name: cwd\n'
59+
b'services:\n'
60+
b' app:\n'
61+
b' image: app:latest\n'
62+
b' networks:\n'
63+
b' default: null\n'
64+
b' user: "0"\n'
65+
b'networks:\n'
66+
b' default:\n'
67+
b' name: cwd_default\n'
68+
)

0 commit comments

Comments
 (0)