1+ # syntax=docker/dockerfile:1
2+ ARG NODE_VERSION=22
3+ ARG PYTHON_VERSION=3.13
4+ ARG POETRY_VERSION=2.1.4
5+ ARG VERSION_OVERRIDE
6+ ARG BRANCH_OVERRIDE
7+
8+ # ############################### Overview
9+
10+ # This Dockerfile builds a Label Studio environment.
11+ # It consists of five main stages:
12+ # 1. "frontend-builder" - Compiles the frontend assets using Node.
13+ # 2. "frontend-version-generator" - Generates version files for frontend sources.
14+ # 3. "venv-builder" - Prepares the virtualenv environment.
15+ # 4. "py-version-generator" - Generates version files for python sources.
16+ # 5. "prod" - Creates the final production image with the Label Studio, Nginx, and other dependencies.
17+
18+ # ############################### Stage: frontend-builder (build frontend assets)
19+ FROM --platform=${BUILDPLATFORM} node:${NODE_VERSION}-trixie AS frontend-builder
20+ ENV BUILD_NO_SERVER=true \
21+ BUILD_NO_HASH=true \
22+ BUILD_NO_CHUNKS=true \
23+ BUILD_MODULE=true \
24+ YARN_CACHE_FOLDER=/root/web/.yarn \
25+ NX_CACHE_DIRECTORY=/root/web/.nx \
26+ NODE_ENV=production
27+
28+ WORKDIR /label-studio/web
29+
30+ # Fix Docker Arm64 Build
31+ RUN yarn config set registry https://registry.npmjs.org/
32+ RUN yarn config set network-timeout 1200000 # HTTP timeout used when downloading packages, set to 20 minutes
33+
34+ COPY web/package.json .
35+ COPY web/yarn.lock .
36+ COPY web/tools tools
37+ RUN --mount=type=cache,target=/root/web/.yarn,id=yarn-cache,sharing=locked \
38+ --mount=type=cache,target=/root/web/.nx,id=nx-cache,sharing=locked \
39+ yarn install --prefer-offline --no-progress --pure-lockfile --frozen-lockfile --ignore-engines --non-interactive --production=false
40+
41+ COPY web/ .
42+ COPY pyproject.toml ../pyproject.toml
43+ RUN --mount=type=cache,target=/root/web/.yarn,id=yarn-cache,sharing=locked \
44+ --mount=type=cache,target=/root/web/.nx,id=nx-cache,sharing=locked \
45+ yarn run build
46+
47+ # ############################### Stage: frontend-version-generator
48+ FROM frontend-builder AS frontend-version-generator
49+ RUN --mount=type=cache,target=/root/web/.yarn,id=yarn-cache,sharing=locked \
50+ --mount=type=cache,target=/root/web/.nx,id=nx-cache,sharing=locked \
51+ --mount=type=bind,source=.git,target=../.git \
52+ yarn version:libs
53+
54+ # ############################### Stage: venv-builder (prepare the virtualenv)
55+ FROM python:${PYTHON_VERSION}-slim-trixie AS venv-builder
56+ ARG POETRY_VERSION
57+
58+ ENV PYTHONUNBUFFERED=1 \
59+ PYTHONDONTWRITEBYTECODE=1 \
60+ PIP_NO_CACHE_DIR=off \
61+ PIP_DISABLE_PIP_VERSION_CHECK=on \
62+ PIP_DEFAULT_TIMEOUT=100 \
63+ PIP_CACHE_DIR="/.cache" \
64+ POETRY_CACHE_DIR="/.poetry-cache" \
65+ POETRY_HOME="/opt/poetry" \
66+ POETRY_VIRTUALENVS_IN_PROJECT=true \
67+ POETRY_VIRTUALENVS_PREFER_ACTIVE_PYTHON=true \
68+ PATH="/opt/poetry/bin:$PATH"
69+
70+ ADD https://install.python-poetry.org /tmp/install-poetry.py
71+ RUN python /tmp/install-poetry.py
72+
73+ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
74+ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
75+ set -eux; \
76+ apt-get update; \
77+ apt-get install --no-install-recommends -y \
78+ build-essential git; \
79+ apt-get autoremove -y
80+
81+ WORKDIR /label-studio
82+
83+
84+ ENV VENV_PATH="/label-studio/.venv"
85+ ENV PATH="$VENV_PATH/bin:$PATH"
86+
87+ # # Starting from this line all packages will be installed in $VENV_PATH
88+
89+ # Copy dependency files
90+ COPY pyproject.toml poetry.lock README.md ./
91+
92+ # Set a default build argument for including dev dependencies
93+ ARG INCLUDE_DEV=false
94+
95+ # Install dependencies
96+ RUN --mount=type=cache,target=/.poetry-cache,id=poetry-cache,sharing=locked \
97+ poetry check --lock && \
98+ if [ "$INCLUDE_DEV" = "true" ]; then \
99+ poetry install --no-root --extras uwsgi --with test; \
100+ else \
101+ poetry install --no-root --without test --extras uwsgi; \
102+ fi
103+
104+ # Install LS
105+ COPY label_studio label_studio
106+ RUN --mount=type=cache,target=/.poetry-cache,id=poetry-cache,sharing=locked \
107+ # `--extras uwsgi` is mandatory here due to poetry bug: https://github.com/python-poetry/poetry/issues/7302
108+ poetry install --only-root --extras uwsgi && \
109+ python3 label_studio/manage.py collectstatic --no-input
110+
111+ # ############################### Stage: py-version-generator
112+ FROM venv-builder AS py-version-generator
113+ ARG VERSION_OVERRIDE
114+ ARG BRANCH_OVERRIDE
115+
116+ # Create version_.py and ls-version_.py
117+ RUN --mount=type=bind,source=.git,target=./.git \
118+ VERSION_OVERRIDE=${VERSION_OVERRIDE} BRANCH_OVERRIDE=${BRANCH_OVERRIDE} poetry run python label_studio/core/version.py
119+
120+ # ################################## Stage: prod
121+ FROM python:${PYTHON_VERSION}-slim-trixie AS production
122+
123+ ENV LS_DIR=/label-studio \
124+ HOME=/label-studio \
125+ LABEL_STUDIO_BASE_DATA_DIR=/label-studio/data \
126+ OPT_DIR=/opt/heartex/instance-data/etc \
127+ PATH="/label-studio/.venv/bin:$PATH" \
128+ DJANGO_SETTINGS_MODULE=core.settings.label_studio \
129+ PYTHONUNBUFFERED=1 \
130+ PYTHONDONTWRITEBYTECODE=1
131+
132+ WORKDIR $LS_DIR
133+
134+ # install prerequisites for app
135+ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
136+ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
137+ set -eux; \
138+ apt-get update; \
139+ apt-get upgrade -y; \
140+ apt-get install --no-install-recommends -y libexpat1 libgl1 libglx-mesa0 libglib2.0-0t64 \
141+ gnupg2 curl nginx \
142+ libopenjp2-7 libnuma1 libspeex1 libvdpau1 libgomp1; \
143+ apt-get autoremove -y
144+
145+ RUN set -eux; \
146+ mkdir -p $LS_DIR $LABEL_STUDIO_BASE_DATA_DIR $OPT_DIR && \
147+ chown -R 1001:0 $LS_DIR $LABEL_STUDIO_BASE_DATA_DIR $OPT_DIR /var/log/nginx /etc/nginx
148+
149+ COPY --chown=1001:0 deploy/default.conf /etc/nginx/nginx.conf
150+
151+ # Copy essential files for installing Label Studio and its dependencies
152+ COPY --chown=1001:0 pyproject.toml .
153+ COPY --chown=1001:0 poetry.lock .
154+ COPY --chown=1001:0 README.md .
155+ COPY --chown=1001:0 LICENSE LICENSE
156+ COPY --chown=1001:0 licenses licenses
157+ COPY --chown=1001:0 deploy deploy
158+
159+ # Copy files from build stages
160+ COPY --chown=1001:0 --from=venv-builder $LS_DIR $LS_DIR
161+ COPY --chown=1001:0 --from=py-version-generator $LS_DIR/label_studio/core/version_.py $LS_DIR/label_studio/core/version_.py
162+ COPY --chown=1001:0 --from=frontend-builder $LS_DIR/web/dist $LS_DIR/web/dist
163+ COPY --chown=1001:0 --from=frontend-version-generator $LS_DIR/web/dist/apps/labelstudio/version.json $LS_DIR/web/dist/apps/labelstudio/version.json
164+ COPY --chown=1001:0 --from=frontend-version-generator $LS_DIR/web/dist/libs/editor/version.json $LS_DIR/web/dist/libs/editor/version.json
165+ COPY --chown=1001:0 --from=frontend-version-generator $LS_DIR/web/dist/libs/datamanager/version.json $LS_DIR/web/dist/libs/datamanager/version.json
166+
167+ USER 1001
168+
169+ EXPOSE 8080
170+
171+ ENTRYPOINT ["./deploy/docker-entrypoint.sh" ]
172+ CMD ["label-studio" ]
0 commit comments