Skip to content

Commit 4fd2ec9

Browse files
Merge pull request #21 from pythoninthegrass/distroless
Distroless
2 parents 3c5eb61 + 682a2cf commit 4fd2ec9

File tree

2 files changed

+81
-80
lines changed

2 files changed

+81
-80
lines changed

Dockerfile

Lines changed: 77 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,108 @@
1-
# using ubuntu LTS version
2-
FROM ubuntu:22.04 AS builder-image
1+
# SOURCES
2+
# https://github.com/alexdmoss/distroless-python
3+
# https://gitlab.com/n.ragav/python-images/-/tree/master/distroless
4+
5+
# full semver just for python base image
6+
ARG PYTHON_VERSION=3.10.7
7+
8+
# several optimisations in python-slim images already, benefit from these
9+
FROM python:${PYTHON_VERSION}-slim-bullseye AS builder-image
310

411
# avoid stuck build due to user prompt
512
ARG DEBIAN_FRONTEND=noninteractive
613

7-
RUN apt-get -qq update \
8-
&& apt-get -qq install \
9-
--no-install-recommends -y \
10-
aptitude \
11-
autoconf \
12-
automake \
13-
build-essential \
14-
ca-certificates \
15-
curl \
16-
git \
17-
locales \
18-
libbz2-dev \
19-
libffi-dev \
20-
libncurses-dev \
21-
libreadline-dev \
22-
libsqlite3-dev \
23-
libssl-dev \
24-
libtool \
25-
libxslt-dev \
26-
libyaml-dev \
27-
python3 \
28-
python3-dev \
29-
python3-pip \
30-
sqlite3 \
31-
unixodbc-dev \
32-
unzip \
33-
&& rm -rf /var/lib/apt/lists/*
14+
# setup standard non-root user for use downstream
15+
ARG USERNAME="appuser"
16+
ARG USER_GROUP=${USERNAME}
17+
ARG HOME="/home/${USERNAME}"
18+
19+
RUN groupadd ${USER_GROUP}
20+
RUN useradd -m ${USERNAME} -g ${USER_GROUP}
21+
22+
# setup user environment with good python practices
23+
USER ${USERNAME}
24+
WORKDIR ${HOME}
25+
ENV PATH="$HOME/.local/bin:$PATH"
3426

3527
# Set locale
36-
RUN locale-gen en_US.UTF-8
3728
ENV LANG=en_US.UTF-8
3829
ENV LANGUAGE=en_US:en
3930
ENV LC_ALL=en_US.UTF-8
4031

41-
ARG USERNAME=appuser
32+
# poetry for use elsewhere as builder image
33+
RUN pip install --upgrade pip \
34+
&& pip install --no-cache-dir --upgrade virtualenv poetry
35+
36+
COPY pyproject.toml poetry.lock ./
37+
RUN poetry config virtualenvs.in-project true \
38+
&& poetry install
39+
40+
# build from distroless C or cc:debug, because lots of Python depends on C
41+
FROM gcr.io/distroless/cc AS distroless
42+
43+
# # arch: x86_64-linux-gnu / aarch64-linux-gnu
44+
# ARG CHIPSET_ARCH=aarch64-linux-gnu
45+
46+
# # required by lots of packages - e.g. six, numpy, wsgi
47+
# COPY --from=builder-image /lib/${CHIPSET_ARCH}/libz.so.1 /lib/${CHIPSET_ARCH}/
48+
49+
# non-root user setup
50+
ARG USERNAME="appuser"
51+
ARG PYTHON_VERSION=3.10
4252
ENV HOME="/home/${USERNAME}"
43-
ENV PATH="$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"
4453

45-
RUN useradd --create-home $USERNAME
54+
# import useful bins from busybox image
55+
COPY --from=busybox:uclibc /bin/ls /bin/ls
56+
COPY --from=busybox:uclibc /bin/rm /bin/rm
57+
COPY --from=busybox:uclibc /bin/sh /bin/sh
58+
COPY --from=busybox:uclibc /bin/find /bin/find
59+
COPY --from=busybox:uclibc /bin/which /bin/which
4660

47-
# install asdf then python latest
48-
RUN bash -c "git clone --depth 1 https://github.com/asdf-vm/asdf.git $HOME/.asdf \
49-
&& echo '. $HOME/.asdf/asdf.sh' >> $HOME/.bashrc \
50-
&& echo '. $HOME/.asdf/asdf.sh' >> $HOME/.profile"
51-
RUN asdf plugin-add python \
52-
&& asdf install python 3.10.7 \
53-
&& asdf global python 3.10.7
61+
ENV VENV="/opt/venv"
62+
COPY --chown=${USERNAME} . /app
63+
COPY --from=builder-image --chown=${USERNAME} "${HOME}/.venv" "$VENV"
64+
COPY --from=builder-image /usr/local/lib/ /usr/local/lib/
65+
COPY --from=builder-image /usr/local/bin/python /usr/local/bin/python
66+
COPY --from=builder-image /etc/ld.so.cache /etc/ld.so.cache
5467

55-
# TODO: test poetry via asdf
56-
ENV POETRY_HOME="$HOME/.poetry"
57-
RUN curl -sSL https://install.python-poetry.org | python3.10 -
58-
ENV PATH "${POETRY_HOME}/bin:$PATH"
68+
ENV PATH="/usr/local/bin:${HOME}/.local/bin:/bin:/usr/bin:${VENV}/bin:${VENV}/lib/python${PYTHON_VERSION}/site-packages:$PATH"
5969

60-
WORKDIR $$HOME/app
61-
COPY pyproject.toml poetry.lock ./
62-
RUN python3.10 -m venv /opt/venv
70+
RUN echo "${USERNAME}:x:1000:${USERNAME}" >> /etc/group
71+
RUN echo "${USERNAME}:x:1001:" >> /etc/group
72+
RUN echo "${USERNAME}:x:1000:1001::/home/${USERNAME}:" >> /etc/passwd
73+
74+
# standardise on locale, don't generate .pyc, enable tracebacks on seg faults
75+
ENV LANG C.UTF-8
76+
ENV LC_ALL C.UTF-8
77+
ENV PYTHONDONTWRITEBYTECODE 1
78+
ENV PYTHONFAULTHANDLER 1
6379

64-
# Install pip requirements
65-
RUN . /opt/venv/bin/activate && poetry install
80+
# remove dev bins (need sh to run `startup.sh`)
81+
RUN rm /bin/find /bin/ls /bin/rm /bin/which
6682

67-
# TODO: dive + docker-slim
68-
FROM ubuntu:22.04 AS runner-image
83+
FROM distroless AS runner-image
6984

85+
ARG PYTHON_VERSION=3.10
7086
ARG USERNAME=appuser
7187
ENV HOME="/home/${USERNAME}"
72-
ENV VIRTUAL_ENV="/opt/venv"
73-
ENV PATH="${VIRTUAL_ENV}/bin:$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"
88+
ENV VENV="/opt/venv"
7489

75-
RUN useradd --create-home $USERNAME \
76-
&& mkdir -p ${HOME}/app
77-
78-
COPY --chown=${USERNAME}:${USERNAME} . $HOME/app
79-
COPY --from=builder-image --chown=${USERNAME}:${USERNAME} /opt/venv /opt/venv
80-
COPY --from=builder-image --chown=${USERNAME}:${USERNAME} $HOME/.asdf $HOME/.asdf
81-
82-
# avoid stuck build due to user prompt
83-
ARG DEBIAN_FRONTEND=noninteractive
90+
ENV PATH="/usr/local/bin:${HOME}/.local/bin:/bin:/usr/bin:${VENV}/bin:${VENV}/lib/python${PYTHON_VERSION}/site-packages:$PATH"
8491

85-
RUN apt-get -qq update \
86-
&& apt-get -qq install \
87-
--no-install-recommends -y \
88-
ca-certificates \
89-
curl \
90-
git \
91-
libsqlite3-dev \
92-
sqlite3 \
93-
&& rm -rf /var/lib/apt/lists/*
94-
95-
# Keeps Python from generating .pyc files in the container
92+
# keeps Python from generating .pyc files in the container
9693
ENV PYTHONDONTWRITEBYTECODE=1
9794

98-
# Turns off buffering for easier container logging
95+
# turns off buffering for easier container logging
9996
ENV PYTHONUNBUFFERED=1
10097

101-
# activate virtual environment
102-
RUN python -m venv $VIRTUAL_ENV
98+
# workers per core (https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker/blob/master/README.md#web_concurrency)
99+
ENV WEB_CONCURRENCY=1
103100

104-
USER appuser
101+
WORKDIR /app
105102

106-
WORKDIR $HOME/app
103+
USER ${USERNAME}
107104

108105
# ENTRYPOINT ["python", "main.py"]
109106
# CMD ["gunicorn", "-c", "config/gunicorn.conf.py", "main:app"]
110-
CMD ["/bin/bash", "startup.sh"]
111-
# CMD ["/bin/bash"]
107+
# CMD ["/bin/sh", "startup.sh"]
108+
CMD ["/bin/sh"]

gunicorn.conf.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
workers = 4
2+
threads = 2
3+
bind = "0.0.0.0:3000"
4+
accesslog = "-"

0 commit comments

Comments
 (0)