Skip to content

Commit 03d1230

Browse files
feat: scratch docker image (#15)
* feat: scratch docker image This moves to a scratch based docker image to reduce image size and attack surface further. The new image uses pyinstaller and staticx to compile the python app to a binary and staticly link it. This binary is copied into a scratch container and set to run as a non root user * ci: update docker ci jobs * ci: remove docker build we test this with the integration test
1 parent ffc4537 commit 03d1230

File tree

3 files changed

+27
-45
lines changed

3 files changed

+27
-45
lines changed

.github/workflows/release.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ jobs:
5252
push: true
5353
tags: ${{ steps.meta.outputs.tags }}
5454
labels: ${{ steps.meta.outputs.labels }}
55-
# we're only using this docker image in gha, so only build a linux/amd64
56-
platforms: linux/amd64
55+
platforms: linux/amd64,linux/arm64
5756
# https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#registry-cache
5857
cache-from: type=gha
5958
cache-to: type=gha,mode=max
@@ -82,8 +81,8 @@ jobs:
8281
env:
8382
GITHUB_TOKEN: ${{ secrets.THIS_PAT }}
8483
with:
85-
tag_name: ${{ inputs.version }}
86-
release_name: ${{ inputs.version }}
87-
body: ${{ inputs.releaseNotes }}
84+
tag_name: ${{ inputs.version }}
85+
release_name: ${{ inputs.version }}
86+
body: ${{ inputs.releaseNotes }}
8887
draft: false
8988
prerelease: ${{ inputs.prerelease }}

Docker/Dockerfile

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,30 @@
1-
FROM python:3.11-slim AS python-base
2-
ADD Docker/builder/rootfs /
3-
ADD repo_manager /app/repo_manager
4-
ADD main.py /app/main.py
1+
FROM python:3.11-slim AS builder
52
WORKDIR /app
63

7-
# We are installing a dependency here directly into our app source dir
8-
RUN pip install --upgrade pip && \
9-
pip install --no-warn-script-location --upgrade virtualenv && \
10-
pip install --target=/app -r /requirements.txt
4+
# install build requirements
5+
RUN apt-get update && apt-get install -y binutils patchelf upx build-essential scons
6+
RUN pip install --no-warn-script-location --upgrade virtualenv pip pyinstaller staticx
117

8+
# copy the app
9+
COPY Docker/builder/rootfs/requirements.txt ./
10+
COPY repo_manager ./repo_manager
11+
COPY main.py ./
1212

13-
# use distroless/cc as the base for our final image
14-
# lots of python depends on glibc
15-
FROM gcr.io/distroless/cc-debian11
13+
## build the app
14+
# install requirements
15+
RUN pip install -r requirements.txt
16+
# pyinstaller package the app
17+
RUN python -OO -m PyInstaller -F main.py --name repo-manager --hidden-import _cffi_backend
18+
# static link the repo-manager binary
19+
RUN cd ./dist && \
20+
staticx repo-manager repo-manager-static
21+
# will be copied over to the scratch container, pyinstaller needs a /tmp to exist
22+
RUN mkdir /app/tmp
1623

17-
# Copy python from the python-builder
18-
# this carries more risk than installing it fully, but makes the image a lot smaller
19-
COPY --from=python-base /usr/local/lib/ /usr/local/lib/
20-
COPY --from=python-base /usr/local/bin/python /usr/local/bin/python
21-
COPY --from=python-base /etc/ld.so.cache /etc/ld.so.cache
2224

23-
# Add some common compiled libraries
24-
# If seeing ImportErrors, check if in the python-base already and copy as below
25-
# required by lots of packages - e.g. six, numpy, wsgi
26-
# *-linux-gnu makes this builder work with either linux/arm64 or linux/amd64
27-
COPY --from=python-base /lib/*-linux-gnu/libz.so.1 /lib/libs/
28-
COPY --from=python-base /usr/lib/*-linux-gnu/libffi* /lib/libs/
29-
COPY --from=python-base /lib/*-linux-gnu/libexpat* /lib/libs/
25+
FROM scratch
3026

31-
# Copy over the app
32-
COPY --from=python-base /app /app
27+
ENTRYPOINT ["/repo-manager"]
3328

34-
35-
# Add /lib/libs to our path
36-
ENV LD_LIBRARY_PATH="/lib/libs:${LD_LIBRARY_PATH}" \
37-
# Add the app path to our path
38-
PATH="/app/bin:${PATH}" \
39-
# Add the app path to your python path
40-
PYTHONPATH="/app:${PYTHONPATH}" \
41-
# standardise on locale, don't generate .pyc, enable tracebacks on seg faults
42-
LANG=C.UTF-8 \
43-
LC_ALL=C.UTF-8 \
44-
PYTHONDONTWRITEBYTECODE=1 \
45-
PYTHONFAULTHANDLER=1
46-
47-
CMD ["python", "/app/main.py"]
29+
COPY --from=builder /app/dist/repo-manager-static /repo-manager
30+
COPY --from=builder /app/tmp /tmp

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ setup-pre-commit:
2121
pre-commit install
2222

2323
build: ## build a docker image locally
24-
docker build --platform linux/amd64 -t gha-repo-manager -f Docker/Dockerfile .
24+
docker build -t gha-repo-manager -f Docker/Dockerfile .
2525

2626
generate-inputs: ## Generate a dict of inputs from actions.yml into repo_manager/utils/__init__.py
2727
./.github/scripts/replace_inputs.sh

0 commit comments

Comments
 (0)