@@ -11,74 +11,120 @@ FROM python:${PYTHON_VERSION}-slim-bullseye AS builder-image
1111# avoid stuck build due to user prompt
1212ARG DEBIAN_FRONTEND=noninteractive
1313
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"
14+ # install dependencies
15+ RUN apt -qq update \
16+ && apt -qq install \
17+ --no-install-recommends -y \
18+ autoconf \
19+ automake \
20+ build-essential \
21+ ca-certificates \
22+ gcc \
23+ libbz2-dev \
24+ libffi7 \
25+ libffi-dev \
26+ liblzma-dev \
27+ libncurses-dev \
28+ libpq-dev \
29+ libreadline-dev \
30+ libsqlite3-dev \
31+ libssl-dev \
32+ libtool \
33+ libxslt-dev \
34+ libyaml-dev \
35+ locales \
36+ lzma \
37+ sqlite3 \
38+ unixodbc-dev \
39+ zlib1g \
40+ && rm -rf /var/lib/apt/lists/*
2641
2742# Set locale
43+ RUN locale-gen en_US.UTF-8
2844ENV LANG=en_US.UTF-8
2945ENV LANGUAGE=en_US:en
3046ENV LC_ALL=en_US.UTF-8
3147
48+ # TODO: debug heroku var interpolation (intermediate containers per ENV??)
49+ # setup standard non-root user for use downstream
50+ ENV USERNAME=appuser
51+ ENV USER_GROUP=${USERNAME}
52+ ENV HOME=/home/${USERNAME}
53+
54+ RUN groupadd ${USERNAME}
55+ RUN useradd -m ${USERNAME} -g ${USERNAME}
56+
57+ # setup user environment
58+ ENV PATH="$HOME/.local/bin:$PATH"
59+
60+ WORKDIR /home/${USERNAME}
61+ USER ${USERNAME}
62+
3263# poetry for use elsewhere as builder image
33- RUN pip install --upgrade pip \
34- && pip install --no-cache-dir --upgrade virtualenv poetry
64+ RUN pip install --user -- upgrade pip \
65+ && pip install --user -- no-cache-dir --upgrade virtualenv poetry
3566
36- COPY pyproject.toml poetry.lock ./
67+ COPY --chown=${USERNAME} pyproject.toml poetry.lock ./
3768RUN poetry config virtualenvs.in-project true \
69+ && poetry config virtualenvs.options.always-copy true \
3870 && poetry install
3971
72+ # # CMD ["/bin/bash"]
73+
4074# build from distroless C or cc:debug, because lots of Python depends on C
4175FROM gcr.io/distroless/cc AS distroless
4276
43- # # arch: x86_64-linux-gnu / aarch64-linux-gnu
44- # ARG CHIPSET_ARCH=aarch64 -linux-gnu
77+ # arch: x86_64-linux-gnu / aarch64-linux-gnu
78+ ARG CHIPSET_ARCH=x86_64 -linux-gnu
4579
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}/
80+ # required by lots of packages - e.g. six, numpy, asgi, wsgi, gunicorn
81+ COPY --from=builder-image /etc/ld.so.cache /etc/
82+ COPY --from=builder-image /lib/${CHIPSET_ARCH}/libz.so.1 /lib/${CHIPSET_ARCH}/
83+ COPY --from=builder-image /lib/${CHIPSET_ARCH}/libexpat.so.1 /lib/${CHIPSET_ARCH}/
84+ COPY --from=builder-image /usr/lib/${CHIPSET_ARCH}/libbz2.so /usr/lib/${CHIPSET_ARCH}/libbz2.so.1.0
85+ COPY --from=builder-image /usr/lib/${CHIPSET_ARCH}/libffi.so.7 /usr/lib/${CHIPSET_ARCH}/
4886
4987# non-root user setup
50- ARG USERNAME=" appuser"
88+ ARG USERNAME=appuser
5189ARG PYTHON_VERSION=3.10
52- ENV HOME="/home/${USERNAME}"
90+ ENV HOME=/home/${USERNAME}
91+ ENV VENV="${HOME}/.venv"
5392
5493# import useful bins from busybox image
5594COPY --from=busybox:uclibc /bin/ls /bin/ls
5695COPY --from=busybox:uclibc /bin/rm /bin/rm
5796COPY --from=busybox:uclibc /bin/sh /bin/sh
97+ COPY --from=busybox:uclibc /bin/vi /bin/vi
98+ COPY --from=busybox:uclibc /bin/cat /bin/cat
5899COPY --from=busybox:uclibc /bin/find /bin/find
59100COPY --from=busybox:uclibc /bin/which /bin/which
101+ COPY --from=busybox:uclibc /bin/env /usr/bin/env
60102
61- ENV VENV="/opt/venv"
103+ # setup standard non-root user for use downstream
104+ ENV USERNAME=appuser
105+ ENV USER_GROUP=${USERNAME}
106+ ENV HOME=/home/${USERNAME}
107+
108+ RUN echo "${USERNAME}:x:1000:${USERNAME}" >> /etc/group
109+ RUN echo "${USERNAME}:x:1001:" >> /etc/group
110+ RUN echo "${USERNAME}:x:1000:1001::/home/${USERNAME}:" >> /etc/passwd
111+
112+ # copy app and virtual environment
62113COPY --chown=${USERNAME} . /app
63- COPY --from=builder-image --chown=${USERNAME} "${HOME}/.venv " "$VENV"
114+ COPY --from=builder-image --chown=${USERNAME} "$VENV " "$VENV"
64115COPY --from=builder-image /usr/local/lib/ /usr/local/lib/
65116COPY --from=builder-image /usr/local/bin/python /usr/local/bin/python
66- COPY --from=builder-image /etc/ld.so.cache /etc/ld.so.cache
67117
68- ENV PATH="/usr/local/bin:${HOME}/.local/bin:/bin:/usr/bin:${VENV}/bin:${VENV}/lib/python${PYTHON_VERSION}/site-packages:$PATH"
118+ ENV PATH="/usr/local/bin:${HOME}/.local/bin:/bin:/usr/bin:${VENV}/bin:${VENV}/lib/python${PYTHON_VERSION}/site-packages:/usr/share/doc: $PATH"
69119
70120RUN echo "${USERNAME}:x:1000:${USERNAME}" >> /etc/group
71121RUN echo "${USERNAME}:x:1001:" >> /etc/group
72122RUN echo "${USERNAME}:x:1000:1001::/home/${USERNAME}:" >> /etc/passwd
73123
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
79-
80124# remove dev bins (need sh to run `startup.sh`)
81- RUN rm /bin/find /bin/ls /bin/rm /bin/which
125+ RUN rm /bin/cat /bin/find /bin/ls /bin/rm /bin/vi /bin/which
126+
127+ # CMD ["/bin/sh"]
82128
83129FROM distroless AS runner-image
84130
@@ -92,12 +138,22 @@ ENV PATH="/usr/local/bin:${HOME}/.local/bin:/bin:/usr/bin:${VENV}/bin:${VENV}/li
92138# keeps Python from generating .pyc files in the container
93139ENV PYTHONDONTWRITEBYTECODE=1
94140
95- # turns off buffering for easier container logging
96- ENV PYTHONUNBUFFERED=1
141+ # standardise on locale, don't generate .pyc, enable tracebacks on seg faults
142+ ENV LANG C.UTF-8
143+ ENV LC_ALL C.UTF-8
144+ ENV PYTHONDONTWRITEBYTECODE 1
145+ ENV PYTHONFAULTHANDLER 1
97146
98147# workers per core (https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker/blob/master/README.md#web_concurrency)
99148ENV WEB_CONCURRENCY=1
100149
150+ COPY --from=busybox:uclibc /bin/chown /bin/chown
151+ COPY --from=busybox:uclibc /bin/rm /bin/rm
152+
153+ RUN chown -R ${USERNAME}:${USERNAME} /app \
154+ && chown -R ${USERNAME}:${USERNAME} ${VENV} \
155+ && rm /bin/chown /bin/rm
156+
101157WORKDIR /app
102158
103159USER ${USERNAME}
0 commit comments