Skip to content

Commit b61127d

Browse files
ci (Dockerfile): refactor to use uv, add generic and django cmds
1 parent 542b5a4 commit b61127d

File tree

1 file changed

+51
-116
lines changed

1 file changed

+51
-116
lines changed
Lines changed: 51 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,88 @@
1-
# syntax=docker/dockerfile:1.7.0
1+
# syntax=docker/dockerfile:1.7.1
22

3-
# full semver just for python base image
4-
ARG PYTHON_VERSION=3.11.11
3+
ARG PYTHON_VERSION=3.12.10
54

6-
FROM python:${PYTHON_VERSION}-slim-bullseye AS builder
5+
FROM python:${PYTHON_VERSION}-slim-bookworm as builder
76

8-
# avoid stuck build due to user prompt
97
ARG DEBIAN_FRONTEND=noninteractive
108

11-
# update apt-get repos and install dependencies
12-
RUN apt-get -qq update \
9+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
10+
--mount=type=cache,target=/var/lib/apt,sharing=locked \
11+
apt-get -qq update \
1312
&& apt-get -qq install --no-install-recommends -y \
13+
build-essential \
14+
ca-certificates \
1415
curl \
1516
gcc \
16-
libpq-dev \
1717
python3-dev \
1818
&& rm -rf /var/lib/apt/lists/*
1919

20-
# pip env vars
21-
ENV PIP_NO_CACHE_DIR=off
22-
ENV PIP_DISABLE_PIP_VERSION_CHECK=on
23-
ENV PIP_DEFAULT_TIMEOUT=100
20+
# venv
21+
ARG UV_PROJECT_ENVIRONMENT="/opt/venv"
22+
ENV VENV="${UV_PROJECT_ENVIRONMENT}"
23+
ENV PATH="$VENV/bin:$PATH"
2424

25-
# poetry env vars
26-
ENV POETRY_HOME="/opt/poetry"
27-
ENV POETRY_VERSION=1.8.5
28-
ENV POETRY_VIRTUALENVS_IN_PROJECT=true
29-
ENV POETRY_NO_INTERACTION=1
25+
# uv
26+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
3027

31-
# path
32-
ENV VENV="/opt/venv"
33-
ENV PATH="$POETRY_HOME/bin:$VENV/bin:$PATH"
28+
ARG WORKDIR="/app"
29+
WORKDIR $WORKDIR
3430

35-
# create app directory and set as working directory
36-
WORKDIR /app
31+
COPY pyproject.toml .
3732

38-
# copy dependencies
39-
COPY requirements.txt requirements.txt
33+
# optimize startup time, don't use hardlinks, set cache for buildkit mount,
34+
# set uv timeout
35+
ENV UV_COMPILE_BYTECODE=1
36+
ENV UV_LINK_MODE=copy
37+
ENV UV_CACHE_DIR=/opt/uv-cache/
38+
ENV UV_HTTP_TIMEOUT=90
4039

41-
# install poetry and dependencies
42-
RUN python -m venv $VENV \
43-
&& . "${VENV}/bin/activate" \
44-
&& python -m pip install "poetry==${POETRY_VERSION}" \
45-
&& python -m pip install -r requirements.txt
40+
RUN --mount=type=cache,target=/opt/uv-cache,sharing=locked \
41+
uv venv $UV_PROJECT_ENVIRONMENT \
42+
&& uv pip install -r pyproject.toml
4643

47-
FROM python:${PYTHON_VERSION}-slim-bullseye AS dev
44+
FROM python:${PYTHON_VERSION}-slim-bookworm as deps
4845

49-
# setup path
50-
ENV VENV="/opt/venv"
51-
ENV PATH="${VENV}/bin:${VENV}/lib/python${PYTHON_VERSION}/site-packages:/usr/local/bin:${HOME}/.local/bin:/bin:/usr/bin:/usr/share/doc:$PATH"
52-
53-
# standardise on locale, don't generate .pyc, enable tracebacks on seg faults
54-
ENV LANG C.UTF-8
55-
ENV LC_ALL C.UTF-8
56-
ENV PYTHONDONTWRITEBYTECODE 1
57-
ENV PYTHONFAULTHANDLER 1
58-
59-
# workers per core
60-
# https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker/blob/master/README.md#web_concurrency
61-
ENV WEB_CONCURRENCY=2
62-
63-
# avoid stuck build due to user prompt
6446
ARG DEBIAN_FRONTEND=noninteractive
6547

66-
# install dependencies
67-
RUN apt-get -qq update \
48+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
49+
--mount=type=cache,target=/var/lib/apt,sharing=locked \
50+
apt-get -qq update \
6851
&& apt-get -qq install --no-install-recommends -y \
69-
bat \
70-
curl \
71-
dpkg \
72-
git \
73-
iputils-ping \
74-
lsof \
75-
make \
76-
p7zip \
77-
perl \
78-
shellcheck \
79-
sudo \
80-
tldr \
81-
tree \
52+
libgomp1 \
8253
&& rm -rf /var/lib/apt/lists/*
8354

84-
# setup standard non-root user for use downstream
55+
FROM deps as runner
56+
57+
ARG WORKDIR="/app"
58+
WORKDIR $WORKDIR
59+
8560
ARG USER_NAME=appuser
8661
ARG USER_UID=1000
8762
ARG USER_GID=$USER_UID
8863

8964
RUN groupadd --gid $USER_GID $USER_NAME \
90-
&& useradd --uid $USER_UID --gid $USER_GID -m $USER_NAME
91-
92-
RUN echo "$USER_NAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER_NAME \
93-
&& chmod 0440 /etc/sudoers.d/$USER_NAME
65+
&& useradd --uid $USER_UID --gid $USER_GID -m $USER_NAME \
66+
&& chown -R $USER_NAME:$USER_NAME /app
9467

95-
# copy virtual environment from builder stage
96-
COPY --from=builder --chown=${USER_NAME}:${USER_GROUP} $VENV $VENV
97-
98-
# qol: tooling
99-
RUN <<EOF
100-
#!/usr/bin/env bash
101-
# fzf
102-
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
103-
yes | ~/.fzf/install
104-
EOF
105-
106-
# switch to non-root user
107-
USER $USER_NAME
68+
ARG VENV="/opt/venv"
69+
ENV PATH=$VENV/bin:$HOME/.local/bin:$PATH
10870

109-
# qol: .bashrc
110-
RUN tee -a "$HOME/.bashrc" <<"EOF"
71+
COPY --from=builder \
72+
--chown=$USER_NAME:$USER_NAME "$VENV" "$VENV"
11173

112-
# shared history
113-
HISTFILE=/var/tmp/.bash_history
114-
HISTFILESIZE=100
115-
HISTSIZE=100
74+
COPY --chown=$USER_NAME:$USER_NAME ./app/ ${WORKDIR}/
11675

117-
stty -ixon
118-
119-
# fzf
120-
[ -f ~/.fzf.bash ] && . ~/.fzf.bash
121-
122-
# asdf
123-
# https://asdf-vm.com/guide/getting-started.html
124-
export ASDF_DIR="$HOME/.asdf"
125-
[[ -f "${ASDF_DIR}/asdf.sh" ]] && . "${ASDF_DIR}/asdf.sh"
126-
127-
# homebrew
128-
export BREW_PREFIX="/home/linuxbrew/.linuxbrew/bin"
129-
[[ -f "${BREW_PREFIX}/brew" ]] && eval "$(${BREW_PREFIX}/brew shellenv)"
130-
131-
# aliases
132-
alias ..='cd ../'
133-
alias ...='cd ../../'
134-
alias ll='ls -la --color=auto'
135-
136-
EOF
137-
138-
FROM dev AS runner
139-
140-
# change working directory
141-
WORKDIR /app
76+
# standardise on locale, don't generate .pyc, enable tracebacks on seg faults
77+
ENV LANG C.UTF-8
78+
ENV LC_ALL C.UTF-8
79+
ENV PYTHONDONTWRITEBYTECODE 1
80+
ENV PYTHONFAULTHANDLER 1
14281

143-
# $PATH
144-
ENV PATH=$VENV_PATH/bin:$HOME/.local/bin:$PATH
82+
USER $USER_NAME
14583

146-
# port needed by app
14784
EXPOSE 8000
14885

149-
# run container indefinitely
15086
CMD ["sleep", "infinity"]
151-
152-
# metadata
153-
LABEL org.opencontainers.image.title="python-class"
87+
# CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
88+
# CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

0 commit comments

Comments
 (0)