[Docker][Analyzers] Investigate changing to alpine in simple analyzers
Summary
I'd like to discuss #13694 (closed) again.
Related MRs:
- gitlab-org/security-products/analyzers/phpcs-security-audit!21 (merged)
- gitlab-org/security-products/analyzers/flawfinder!18 (merged)
- gitlab-org/security-products/analyzers/bandit!26 (closed)
- gitlab-org/security-products/analyzers/brakeman!22 (closed)
- gitlab-org/security-products/analyzers/bundler-audit!39 (closed)
- Consider revert gitlab-org/security-products/analyzers/gemnasium-python!37 (merged)
cc @fcatteau
Improvements
Alpine Linux has a much smaller footprint than Debian. This makes Alpine Linux a great image base for utilities and even production applications. There are already a lot of analyzer images based on node:alpine
or golang:alpine
.
Previous discussion regarding gemnasium-python
This section is specific to gitlab-org/security-products/analyzers/gemnasium-python!37 (merged). I think this image can be considered as a trivial image where the base OS doesn't matter (see Risks section).
obsolete PEP 571
The decision was based on PEP 571, which has been superseded by PEP 599 and PEP 600. While "handling non-glibc-based platforms" is a non-goal of PEP 600, it mentions a lot of issues with prebuilt binaries. In fact Debian or any other base image will run into the same issues if you have special requirements (mostly closed source) like Python packages compiled with CUDA. If they're linked against glibc, some of them can be run with libc6-compat on Alpine. See also &1858 (closed)
If the correct dependencies are installed, Python packages can be installed on Alpine Linux. pillow
was mentioned as an example that did not work for some. I think this was just an issue with dependencies. Here is a full example installing pillow and optionally removing build dependencies afterwards:
Dockerfile example
FROM python:alpine
# Let's assume git is required during runtime
RUN apk add --no-cache git
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
freetype-dev \
gcc \
lcms2-dev \
libjpeg-turbo-dev \
libpng-dev \
libwebp-dev \
musl-dev \
tiff-dev \
zlib-dev \
; \
pip install --no-cache-dir pillow; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/python3.8 \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --virtual .app-rundeps $runDeps; \
apk del .build-deps
In my own experience it's more likely to run in compatibility issues with the Python version (e.g. 3.6
vs. 3.8
or non x86 architectures than with the C library. Alpine itself provides hundreds of Python packages.
build-essential
Installing gitlab-org/security-products/analyzers/gemnasium-python!37 (merged) is based on debian:slim
, but it installs build-essential
. This should be avoided on "slim" images. There is the buildpack-deps for such needs, but I think this is not what you want here.
If Debian is used as a base image, unnecessary build dependencies should be removed after pip install
(see the Alpine example above). build-essential
installs a lot of Debian specific packages like dpkg-dev
that are not required at all. This can be changed with low risks/side effects. It's unlikely that this image is used to build Debian packages.
Risks
Alpine Linux makes sense for trivial Docker containers and an Alpine variant is also maintained upstream. If an image is expected to get heavily customized or run prebuild binaries, it should stick with Debian(-slim). I prepared MRs for images I'd consider for this change.
Involved components
Trivial Dockerfile
s using FROM debian
, see MR above.
Optional: Intended side effects
As stated in gitlab-org/security-products/analyzers/bundler-audit!37 (comment 337146024), if users customize the image using apt
or other OS specific commands, they need to migrate them as well. I don't know if this a common issue or not. You provide the best experience for both, users that need OS specific customization and for them just running the image as it is.