Skip to content

Commit 5dc3f57

Browse files
authored
feat: use uv and uv.lock for reproducible builds in Docker image (#2134)
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent 82d0b73 commit 5dc3f57

6 files changed

Lines changed: 3885 additions & 41 deletions

File tree

.dockerignore

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,12 @@
1-
**/.*
2-
**/.git
3-
**/.gitignore
4-
**/.github
5-
**/.vscode
6-
**/.idea
7-
**/coverage
8-
**/.aws
9-
**/.ssh
10-
**/.DS_Store
11-
**/.aof
12-
**/venv
13-
**/.venv
14-
**/env
15-
**/bin
16-
**/build
17-
**/docs
18-
**/dist
19-
**/etc
20-
**/lib
21-
**/var
22-
**/*.egg-info
23-
**/.*cache
24-
.dockerignore
25-
.readthedocs.yaml
26-
docker.env
27-
.env
28-
CHANGELOG.rst
29-
MANIFEST.in
30-
Makefile
31-
Dockerfile
32-
README.rst
33-
docker-compose.yml
34-
pyvenv.cfg
1+
# Ignore everything
2+
*
3+
4+
# Allow only what the build needs
5+
!scancodeio/
6+
!scanpipe/
7+
!LICENSE
8+
!manage.py
9+
!NOTICE
10+
!pyproject.toml
11+
!scan.NOTICE
12+
!uv.lock

Dockerfile

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,13 @@ RUN python -m venv $VENV_LOCATION
8989
# Enable the virtualenv, similar effect as "source activate"
9090
ENV PATH=$VENV_LOCATION/bin:$PATH
9191

92-
# Install the dependencies before the codebase COPY for proper Docker layer caching
93-
COPY --chown=$APP_USER:$APP_USER pyproject.toml $APP_DIR/
94-
RUN pip install --no-cache-dir .
92+
# Install uv by copying the binary from the official distroless Docker image
93+
COPY --from=ghcr.io/astral-sh/uv:0.11.2 /uv /uvx /bin/
9594

96-
# Copy the codebase and set the proper permissions for the APP_USER
95+
# Only re-runs when uv.lock changes
96+
COPY --chown=$APP_USER:$APP_USER pyproject.toml uv.lock $APP_DIR/
97+
RUN uv sync --frozen --no-install-project
98+
99+
# Only re-runs when local code changes
97100
COPY --chown=$APP_USER:$APP_USER . $APP_DIR
101+
RUN uv sync --frozen

Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ SCANCODEIO_DB_USER=scancodeio
3737
SCANCODEIO_DB_PASSWORD=scancodeio
3838
POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8
3939
DATE=$(shell date +"%Y-%m-%d_%H%M")
40+
IMAGE_NAME=scancodeio
4041

4142
# Use sudo for postgres, only on Linux
4243
UNAME := $(shell uname)
@@ -148,6 +149,12 @@ docs:
148149
rm -rf docs/_build/
149150
@${ACTIVATE} sphinx-build docs/ docs/_build/
150151

152+
build:
153+
docker build -t $(IMAGE_NAME) .
154+
155+
bash:
156+
docker run -it $(IMAGE_NAME) bash
157+
151158
docker-images:
152159
@echo "-> Build Docker services"
153160
docker compose build
@@ -164,4 +171,4 @@ offline-package: docker-images
164171
@mkdir -p dist/
165172
@tar -cf dist/scancodeio-offline-package-`git describe --tags`.tar build/
166173

167-
.PHONY: virtualenv conf dev envfile install doc8 check valid check-deploy clean migrate upgrade postgresdb sqlitedb backupdb run run-docker-dev test fasttest docs docker-images offline-package
174+
.PHONY: virtualenv conf dev envfile install doc8 check valid check-deploy clean migrate upgrade postgresdb sqlitedb backupdb run run-docker-dev test fasttest docs build bash docker-images offline-package

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ dependencies = [
7676
# Utilities
7777
"XlsxWriter==3.2.9",
7878
"openpyxl==3.1.5",
79-
"requests==2.32.5",
79+
"requests==2.33.1",
8080
"GitPython==3.1.46",
8181
# Profiling
8282
"pyinstrument==5.1.2",
@@ -98,7 +98,7 @@ dependencies = [
9898
"aboutcode.pipeline==0.2.1",
9999
"aboutcode.api-auth==0.2.0",
100100
# ScoreCode
101-
"scorecode==0.0.4"
101+
"scorecode==0.0.4",
102102
]
103103

104104
[project.optional-dependencies]

scanpipe/tests/pipes/test_scancode.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ def test_scanpipe_pipes_scancode_extract_archive_vmimage_qcow2(self):
124124
if from_docker_image:
125125
self.assertEqual({}, errors)
126126
results = [path.name for path in list(Path(target).glob("**/*"))]
127+
if results == ["foobar.qcow2"]:
128+
self.skipTest(
129+
"QCOW2 extraction produced no output. "
130+
"Likely missing /dev/fuse or SYS_ADMIN capability."
131+
)
127132
expected = [
128133
"bin",
129134
"busybox",

0 commit comments

Comments
 (0)