* export_datatable_schema * Propose to fork the datatable on ws fork * dump datatable * Dockerfile * Fix import_datatable_dump * datatable schema fork works! * Option to copy both schema and data * Datatable fork behavior * nit ui * use psql instead * remove fork_datatable route * feat: add fork_pg_database and export_pg_schema routes with DB Manager UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: pluralize "schema" to "schemas" in DB Manager export/import UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add import mode select (schema only vs schema + data) to DB Manager import Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Select schema or schema+data when important database * fix: prepend $res: prefix to resource paths in DB Manager import/export Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: dynamic import button label based on selected mode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nits * feat: add warning alert when schema+data import mode is selected Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nit hide on cloud hosted * refactor: remove fork_behavior from datatable settings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: split CreateWorkspace into layout wrapper and CreateWorkspaceInner Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: instantiate CreateWorkspaceInner in globalForkModal Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nit icons * Data table fork UI * feat: pass per-datatable fork behaviors from UI to backend during workspace fork Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix fork overwriting all datatables * UI nits * custom instance db refactor * custom instance db wizard btn for all in dropdown * nit * Delete custom instance database button * Disable forking for resource datatables * Big import buttons when db empty * Revert "Disable forking for resource datatables" This reverts commit9561cc8fd4. * feat: add non_diffable flag to resource table Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add resource-type datatable fork with CREATE DATABASE Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: tag forked datatables with nonDiffable and forkedFrom Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: diff datatable and ducklake settings individually on workspace merge Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: skip non_diffable resources and datatables in workspace diff Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: default datatable fork behavior to keep_original Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: make grant permissions non-fatal in instance datatable fork Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: make datatable and ducklake diffs visible in workspace comparison Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: remove datatable fork logic from workspace fork route Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: correct ahead/behind logic for datatable and ducklake diffs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert "fix: correct ahead/behind logic for datatable and ducklake diffs" This reverts commit6b50884dc6. * revert: remove datatable and ducklake settings diffing logic Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add datatable clone UI with step-by-step confirmation modal Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract datatable fork UI into ForkDatatableSection component Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit * fix: run datatable cloning before workspace fork creation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit disable fork admins * nit fix switching workspace prematurely * fix: use source workspace for forkPgDatabase calls during fork Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: update forked workspace datatable settings after fork creation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add forked_from field to DataTable and set it for instance forks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit onFinish * fix: add forked_from to DataTableSettings OpenAPI schema Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: track datatable table DDL changes in workspace_diff Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert "feat: track datatable table DDL changes in workspace_diff" This reverts commit7526dd68b9. * feat: add get_datatable_full_schema endpoint and snapshot schema on fork Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix duplicate migration key * fix: set forked_from on datatable config for both instance and resource types Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nits * feat: drop forked databases on workspace deletion with confirmation UI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract drop_forked_datatable_databases from delete_workspace Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: cast pg char columns to text in FK schema query Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: show dbname instead of resource type in fork deletion modal Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * ui nit * refactor: extract drop_custom_instance_database into windmill-common Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add datatable schema diff section to merge UI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * UI * feat: add review drawer with YAML diff and SQL migration runner Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: use Monaco DiffEditor for YAML diff in review drawer Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit * Revert "refactor: use Monaco DiffEditor for YAML diff in review drawer" This reverts commita86008ba4c. * Revert "feat: add review drawer with YAML diff and SQL migration runner" This reverts commit0a0deb5ddb. * feat: add review drawer with DiffEditor and SQL migration runner Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * ui nits * fix: show diff between forked_from schema and changed side Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: re-fetch target live schema after migration for correct baseline Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * revert * nit auto next * feat: add confirmation modal before deploying migration to parent Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: handle missing columns/foreignKeys in schema conversion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nits * refactor: use temp file on disk for pg_dump instead of in-memory string Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Don't replace postgres dbname * fix: add validation to drop_custom_instance_database and use source db for CREATE/DROP Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: type DataTable.forked_from as DataTableForkedFrom struct Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: simplify fork_pg_database to take source + target_dbname Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * dead code * feat: enforce schema_and_data admin-only and extract create_custom_instance_database Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: rename fork_pg_database to import_pg_database with source/target/override params Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit * refactor: remove original_dbname/original_resource from forked_from, resolve from parent Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit * fix: resolve forked dbname from fork workspace when dropping resource databases Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nits * fix: always clean up global_settings even if database doesn't exist Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: check datatable resource_type from config instead of URL prefix Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: wrap PG default value expressions in braces to prevent CAST quoting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert "fix: wrap PG default value expressions in braces to prevent CAST quoting" This reverts commit77f5a2c4e8. * refactor: reuse columnDefToTableEditorValuesColumn for default value handling Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: store raw API schema in forked_from to avoid double transformation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert "fix: store raw API schema in forked_from to avoid double transformation" This reverts commite326197a20. * Revert "refactor: reuse columnDefToTableEditorValuesColumn for default value handling" This reverts commitbd8f071d9f. * fix: validate dbname with strict regex to prevent SQL injection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix default value * always validate dbname * refactor: move get_datatable_full_schema structs and logic to query_builders.rs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: split import_pg_database into create_pg_database + import_pg_database Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract drop_forked_datatable_databases into its own route Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: require admin when using $res: resource paths in import_pg_database Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use UserDB for $res: resource access and restrict dbname creation - resolve_pg_source_checked uses UserDB (row-level security) for $res: paths - transform_json_unchecked is now pub(crate) to prevent misuse - Non-superadmins can only create databases with wm_fork_ prefix - datatable:// remains accessible to everyone Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: refuse to drop forked databases unless name starts with wm_fork_ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: remove resolve_pg_source, use resolve_pg_source_checked everywhere Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix permissions * sqlx prepare * compilation nits * sqlx prepare * sqlx prepare * wrong route syntax * fix: allow workspace owner to edit datatable config for fork setup Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert "fix: allow workspace owner to edit datatable config for fork setup" This reverts commitab683e637b. * refactor: move datatable fork setup into create_workspace_fork backend Instead of updating datatable settings from the frontend after fork creation (which required admin/owner access), pass forked_datatables info to create_workspace_fork and handle it atomically in the same transaction. Removes applyPostForkDatatableUpdates from frontend. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: snapshot schema in backend during fork instead of frontend The schema snapshot is now taken by the backend in apply_forked_datatable via snapshot_datatable_schema, which connects to the parent workspace's datatable and runs pg_get_full_schema. This removes the need for the frontend to call getDatatableFullSchema and pass the schema through. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use get_resource_value_interpolated_internal for $res: to resolve $var: references Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit * sqlx prepare * fix: add permission check to drop_forked_datatable_databases, validate dbnames, restrict temp file perms - drop_forked_datatable_databases: same permission as delete_workspace (fork owner or super admin) - validate_dbname on target_dbname_override and ForkedDatatableInfo.new_dbname - Enforce wm_fork_ prefix on forked datatable new_dbname - DumpFile: set /tmp/windmill/ to 0700 and create files with 0600 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * nit CLI * Rename to ws_specific * sqlx prepare * nit always validate dbname * fix: include foreign keys in CREATE TABLE migration for added tables Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: detect nextval defaults and use SERIAL/BIGSERIAL types in CREATE TABLE Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Update frontend/src/lib/components/DBManagerDrawer.svelte Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update backend/windmill-common/src/lib.rs Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update backend/windmill-common/src/lib.rs Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * fix: sort foreign keys by constraint name for deterministic schema output Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * sqlx prepare * rename migration to update timestamp --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
330 lines
13 KiB
Docker
330 lines
13 KiB
Docker
ARG DEBIAN_IMAGE=debian:bookworm-slim
|
|
ARG RUST_IMAGE=rust:1.93-slim-bookworm
|
|
|
|
FROM debian:bookworm-slim AS nsjail
|
|
|
|
WORKDIR /nsjail
|
|
|
|
RUN apt-get -y update \
|
|
&& apt-get install -y \
|
|
bison=2:3.8.* \
|
|
flex=2.6.* \
|
|
g++=4:12.2.* \
|
|
gcc=4:12.2.* \
|
|
git=1:2.39.* \
|
|
libprotobuf-dev=3.21.* \
|
|
libnl-route-3-dev=3.7.* \
|
|
make=4.3-4.1 \
|
|
pkg-config=1.8.* \
|
|
protobuf-compiler=3.21.*
|
|
|
|
RUN git clone -b master --single-branch https://github.com/google/nsjail.git . && git checkout dccf911fd2659e7b08ce9507c25b2b38ec2c5800
|
|
RUN make
|
|
|
|
FROM ${RUST_IMAGE} AS rust_base
|
|
|
|
RUN apt-get update && apt-get install -y git libssl-dev pkg-config npm mold clang
|
|
|
|
RUN apt-get -y update \
|
|
&& apt-get install -y \
|
|
curl nodejs
|
|
|
|
RUN rustup component add rustfmt
|
|
|
|
RUN CARGO_NET_GIT_FETCH_WITH_CLI=true cargo install cargo-chef --version 0.1.68
|
|
RUN cargo install sccache --version ^0.8
|
|
ENV RUSTC_WRAPPER=sccache SCCACHE_DIR=/backend/sccache
|
|
|
|
WORKDIR /windmill
|
|
|
|
ENV SQLX_OFFLINE=true
|
|
# ENV CARGO_INCREMENTAL=1
|
|
|
|
FROM rust_base AS windmill_duckdb_ffi_internal_builder
|
|
|
|
WORKDIR /windmill-duckdb-ffi-internal
|
|
|
|
RUN apt-get update && apt-get install -y clang=1:14.0-55.* libclang-dev=1:14.0-55.* cmake=3.25.* && \
|
|
apt-get clean && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
COPY ./backend/windmill-duckdb-ffi-internal .
|
|
|
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
|
cargo build --release -p windmill_duckdb_ffi_internal
|
|
|
|
FROM node:24-alpine as frontend
|
|
|
|
# install dependencies
|
|
WORKDIR /frontend
|
|
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/.npmrc ./
|
|
COPY ./frontend/scripts/ ./scripts/
|
|
RUN npm ci
|
|
|
|
# Copy all local files into the image.
|
|
COPY frontend .
|
|
RUN mkdir /backend
|
|
COPY /backend/windmill-api/openapi.yaml /backend/windmill-api/openapi.yaml
|
|
COPY /openflow.openapi.yaml /openflow.openapi.yaml
|
|
COPY /backend/windmill-api/build_openapi.sh /backend/windmill-api/build_openapi.sh
|
|
COPY /system_prompts/auto-generated /system_prompts/auto-generated
|
|
|
|
RUN cd /backend/windmill-api && . ./build_openapi.sh
|
|
COPY /backend/parsers/windmill-parser-wasm/pkg/ /backend/parsers/windmill-parser-wasm/pkg/
|
|
COPY /typescript-client/docs/ /frontend/static/tsdocs/
|
|
COPY /python-client/docs/ /frontend/static/pydocs/
|
|
|
|
RUN npm run generate-backend-client
|
|
ENV NODE_OPTIONS "--max-old-space-size=8192"
|
|
ARG VITE_BASE_URL ""
|
|
# Read more about macro in docker/dev.nu
|
|
# -- MACRO-SPREAD-WASM-PARSER-DEV-ONLY -- #
|
|
RUN npm run build
|
|
|
|
|
|
FROM rust_base AS planner
|
|
|
|
COPY ./openflow.openapi.yaml /openflow.openapi.yaml
|
|
COPY ./backend ./
|
|
|
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
|
CARGO_NET_GIT_FETCH_WITH_CLI=true cargo chef prepare --recipe-path recipe.json
|
|
|
|
FROM rust_base AS builder
|
|
ARG features=""
|
|
|
|
COPY --from=planner /windmill/recipe.json recipe.json
|
|
|
|
RUN apt-get update && apt-get install -y libxml2-dev=2.9.* libxmlsec1-dev=1.2.* libkrb5-dev libsasl2-dev libcurl4-openssl-dev clang=1:14.0-55.* libclang-dev=1:14.0-55.* cmake=3.25.* && \
|
|
apt-get clean && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
|
CARGO_NET_GIT_FETCH_WITH_CLI=true RUST_BACKTRACE=1 cargo chef cook --release --features "$features" --recipe-path recipe.json
|
|
|
|
COPY ./openflow.openapi.yaml /openflow.openapi.yaml
|
|
COPY ./backend ./
|
|
|
|
RUN mkdir -p /frontend
|
|
|
|
COPY --from=frontend /frontend/build /frontend/build
|
|
COPY --from=frontend /backend/windmill-api/openapi-deref.yaml ./windmill-api/openapi-deref.yaml
|
|
COPY .git/ .git/
|
|
|
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
|
CARGO_NET_GIT_FETCH_WITH_CLI=true cargo build --release --features "$features"
|
|
|
|
# Split debug info into a separate file, then strip the binary.
|
|
# The .debug file can be extracted as a CI artifact for production debugging.
|
|
# The debuglink allows gdb to auto-discover the debug file when placed next to the binary.
|
|
RUN objcopy --only-keep-debug /windmill/target/release/windmill /windmill/target/release/windmill.debug \
|
|
&& strip /windmill/target/release/windmill \
|
|
&& objcopy --add-gnu-debuglink=/windmill/target/release/windmill.debug /windmill/target/release/windmill
|
|
|
|
# Standalone stage for extracting the .debug file without including it in the final image.
|
|
# Build with: docker build --target debuginfo --output type=local,dest=./out .
|
|
FROM scratch AS debuginfo
|
|
COPY --from=builder /windmill/target/release/windmill.debug /windmill.debug
|
|
|
|
FROM ${DEBIAN_IMAGE}
|
|
|
|
ARG TARGETPLATFORM
|
|
ARG POWERSHELL_VERSION=7.5.0
|
|
ARG POWERSHELL_DEB_VERSION=7.5.0-1
|
|
ARG KUBECTL_VERSION=1.28.7
|
|
ARG HELM_VERSION=3.14.3
|
|
# NOTE: If changing, also change go version in workspace dependencies template at WorkspaceDependenciesEditor.svelte
|
|
ARG GO_VERSION=1.26.0
|
|
ARG APP=/usr/src/app
|
|
ARG WITH_POWERSHELL=true
|
|
ARG WITH_KUBECTL=true
|
|
ARG WITH_HELM=true
|
|
ARG WITH_GIT=true
|
|
ARG features=""
|
|
|
|
# To change latest stable version:
|
|
# 1. Change placeholder in instanceSettings.ts
|
|
# 2. Change LATEST_STABLE_PY in dockerfile
|
|
# 3. Change #[default] annotation for PyVersion in backend
|
|
ARG LATEST_STABLE_PY=3.12
|
|
ENV UV_PYTHON_INSTALL_DIR=/tmp/windmill/cache/py_runtime
|
|
ENV UV_PYTHON_PREFERENCE=only-managed
|
|
|
|
RUN mkdir -p /usr/local/uv
|
|
ENV UV_TOOL_BIN_DIR=/usr/local/bin
|
|
ENV UV_TOOL_DIR=/usr/local/uv
|
|
|
|
ENV PATH /usr/local/bin:/root/.local/bin:/tmp/.local/bin:$PATH
|
|
|
|
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends netbase tzdata ca-certificates wget curl jq unzip build-essential unixodbc xmlsec1 software-properties-common tini gnupg lsb-release \
|
|
&& if echo "$features" | grep -q "ee"; then apt-get install -y --no-install-recommends libsasl2-modules-gssapi-mit krb5-user; fi \
|
|
&& apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install latest PostgreSQL client (pg_dump) from official PostgreSQL apt repository
|
|
RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/postgresql-archive-keyring.gpg \
|
|
&& echo "deb [signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list \
|
|
&& apt-get update \
|
|
&& apt-get install -y --no-install-recommends postgresql-client \
|
|
&& apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN if [ "$WITH_GIT" = "true" ]; then \
|
|
apt-get update -y \
|
|
&& apt-get install -y git \
|
|
&& apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/*; \
|
|
else echo 'Building the image without git'; fi;
|
|
|
|
RUN if [ "$WITH_POWERSHELL" = "true" ]; then \
|
|
if [ "$TARGETPLATFORM" = "linux/amd64" ]; then apt-get update -y && apt install libicu-dev -y && wget -O 'pwsh.deb' "https://github.com/PowerShell/PowerShell/releases/download/v${POWERSHELL_VERSION}/powershell_${POWERSHELL_DEB_VERSION}.deb_amd64.deb" && apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/* && \
|
|
dpkg --install 'pwsh.deb' && \
|
|
rm 'pwsh.deb'; \
|
|
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then apt-get update -y && apt install libicu-dev -y && wget -O powershell.tar.gz "https://github.com/PowerShell/PowerShell/releases/download/v${POWERSHELL_VERSION}/powershell-${POWERSHELL_VERSION}-linux-arm64.tar.gz" && apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/* && \
|
|
mkdir -p /opt/microsoft/powershell/7 && \
|
|
tar zxf powershell.tar.gz -C /opt/microsoft/powershell/7 && \
|
|
chmod +x /opt/microsoft/powershell/7/pwsh && \
|
|
ln -s /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh && \
|
|
rm powershell.tar.gz; \
|
|
else echo 'Could not install pwshell, not on amd64 or arm64'; fi; \
|
|
else echo 'Building the image without powershell'; fi
|
|
|
|
RUN if [ "$WITH_HELM" = "true" ]; then \
|
|
arch="$(dpkg --print-architecture)"; arch="${arch##*-}"; \
|
|
wget "https://get.helm.sh/helm-v${HELM_VERSION}-linux-$arch.tar.gz" && \
|
|
tar -zxvf "helm-v${HELM_VERSION}-linux-$arch.tar.gz" && \
|
|
mv linux-$arch/helm /usr/local/bin/helm &&\
|
|
chmod +x /usr/local/bin/helm; \
|
|
else echo 'Building the image without helm'; fi
|
|
|
|
RUN if [ "$WITH_KUBECTL" = "true" ]; then \
|
|
arch="$(dpkg --print-architecture)"; arch="${arch##*-}"; \
|
|
curl -LO "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/$arch/kubectl" && \
|
|
install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl; \
|
|
else echo 'Building the image without kubectl'; fi
|
|
|
|
|
|
RUN set -eux; \
|
|
arch="$(dpkg --print-architecture)"; arch="${arch##*-}"; \
|
|
case "$arch" in \
|
|
"amd64") \
|
|
targz="go${GO_VERSION}.linux-amd64.tar.gz"; \
|
|
;; \
|
|
"arm64") \
|
|
targz="go${GO_VERSION}.linux-arm64.tar.gz"; \
|
|
;; \
|
|
"armhf") \
|
|
targz="go${GO_VERSION}.linux-armv6l.tar.gz"; \
|
|
;; \
|
|
*) echo >&2 "error: unsupported architecture '$arch' (likely packaging update needed)"; exit 1 ;; \
|
|
esac; \
|
|
wget "https://golang.org/dl/$targz" -nv && tar -C /usr/local -xzf "$targz" && rm "$targz";
|
|
|
|
ENV PATH="${PATH}:/usr/local/go/bin"
|
|
ENV GO_PATH=/usr/local/go/bin/go
|
|
|
|
# Install UV
|
|
RUN curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/uv/releases/download/0.9.24/uv-installer.sh | sh && mv /root/.local/bin/uv /usr/local/bin/uv
|
|
|
|
# Preinstall python runtimes to temp build location (will copy with world-writable perms later)
|
|
RUN UV_CACHE_DIR=/tmp/build_cache/uv UV_PYTHON_INSTALL_DIR=/tmp/build_cache/py_runtime uv python install 3.11
|
|
RUN UV_CACHE_DIR=/tmp/build_cache/uv UV_PYTHON_INSTALL_DIR=/tmp/build_cache/py_runtime uv python install $LATEST_STABLE_PY
|
|
|
|
|
|
RUN curl -sL https://deb.nodesource.com/setup_20.x | bash -
|
|
RUN apt-get -y update && apt-get install -y curl procps nodejs awscli && apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# go build is slower the first time it is ran, so we prewarm it in the build
|
|
# This mirrors Windmill's Go wrapper structure: main.go imports inner package, uses encoding/json, os, fmt
|
|
RUN export GOCACHE=/tmp/build_cache/go && \
|
|
mkdir -p /tmp/gobuildwarm/inner && \
|
|
cd /tmp/gobuildwarm && \
|
|
go mod init mymod && \
|
|
printf 'package main\nimport (\n\t"encoding/json"\n\t"os"\n\t"fmt"\n\t"mymod/inner"\n)\nfunc main() {\n\tdat, _ := os.ReadFile("args.json")\n\tvar req inner.Req\n\tjson.Unmarshal(dat, &req)\n\tres, _ := inner.Run(req)\n\tres_json, _ := json.Marshal(res)\n\tfmt.Println(string(res_json))\n}' > main.go && \
|
|
printf 'package inner\ntype Req struct {\n\tX int `json:"x"`\n}\nfunc Run(req Req) (interface{}, error) {\n\treturn main(req.X)\n}\nfunc main(x int) (interface{}, error) {\n\treturn x, nil\n}' > inner/inner.go && \
|
|
go build -x . && \
|
|
rm -rf /tmp/gobuildwarm
|
|
|
|
# Copy build caches to final location, then add write permissions for any UID
|
|
# chmod a+rw adds read+write WITHOUT removing execute bits (755->777, 644->666)
|
|
# Note: uv python install only creates py_runtime, not uv cache - we create uv/go dirs for runtime
|
|
RUN mkdir -p /tmp/windmill/cache && \
|
|
cp -r /tmp/build_cache/* /tmp/windmill/cache/ && \
|
|
chmod -R a+rw /tmp/windmill/cache && \
|
|
rm -rf /tmp/build_cache && \
|
|
mkdir -p -m 777 /tmp/windmill/cache/uv /tmp/windmill/cache/go /tmp/windmill/cache/rustup /tmp/windmill/cache/cargo
|
|
|
|
# Runtime cache locations
|
|
ENV UV_CACHE_DIR=/tmp/windmill/cache/uv
|
|
ENV UV_PYTHON_INSTALL_DIR=/tmp/windmill/cache/py_runtime
|
|
ENV GOCACHE=/tmp/windmill/cache/go
|
|
|
|
ENV TZ=Etc/UTC
|
|
|
|
COPY --from=builder /frontend/build /static_frontend
|
|
COPY --from=builder /windmill/target/release/windmill ${APP}/windmill
|
|
COPY --from=windmill_duckdb_ffi_internal_builder /windmill-duckdb-ffi-internal/target/release/libwindmill_duckdb_ffi_internal.so ${APP}/libwindmill_duckdb_ffi_internal.so
|
|
|
|
COPY --from=denoland/deno:2.2.1 --chmod=755 /usr/bin/deno /usr/bin/deno
|
|
|
|
COPY --from=oven/bun:1.3.10 /usr/local/bin/bun /usr/bin/bun
|
|
|
|
# Install windmill CLI
|
|
RUN bun install -g windmill-cli \
|
|
&& ln -s $(bun pm bin -g)/wmill /usr/bin/wmill
|
|
|
|
# Install Claude Code CLI (used by claude sandbox scripts)
|
|
# The installer puts the binary in ~/.local/bin/claude (symlink to ~/.local/share/claude/versions/*)
|
|
# Copy it to /usr/bin/claude so it's accessible inside nsjail sandbox (which mounts /usr but not /root)
|
|
RUN curl -fsSL https://claude.ai/install.sh | bash \
|
|
&& cp /root/.local/share/claude/versions/* /usr/bin/claude
|
|
|
|
COPY --from=php:8.3.30-cli-bookworm /usr/local/bin/php /usr/bin/php
|
|
COPY --from=composer:2.9.5 /usr/bin/composer /usr/bin/composer
|
|
|
|
# add the docker client to call docker from a worker if enabled
|
|
COPY --from=docker:29-dind /usr/local/bin/docker /usr/local/bin/
|
|
|
|
ENV RUSTUP_HOME="/tmp/windmill/cache/rustup"
|
|
ENV CARGO_HOME="/tmp/windmill/cache/cargo"
|
|
ENV LD_LIBRARY_PATH="."
|
|
|
|
# nsjail runtime deps and binary
|
|
RUN apt-get update && apt-get install -y libprotobuf-dev libnl-route-3-dev \
|
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
COPY --from=nsjail /nsjail/nsjail /bin/nsjail
|
|
|
|
WORKDIR ${APP}
|
|
|
|
RUN ln -s ${APP}/windmill /usr/local/bin/windmill
|
|
|
|
COPY ./frontend/src/lib/hubPaths.json ${APP}/hubPaths.json
|
|
|
|
RUN windmill cache ${APP}/hubPaths.json && rm ${APP}/hubPaths.json
|
|
|
|
RUN windmill cache-rt
|
|
|
|
# Create a non-root user 'windmill' with UID and GID 1000
|
|
RUN addgroup --gid 1000 windmill && \
|
|
adduser --disabled-password --gecos "" --uid 1000 --gid 1000 windmill
|
|
|
|
# /tmp/.cache may be created by earlier build steps with 755; chmod ensures any UID can write
|
|
RUN mkdir -p -m 777 /tmp/windmill/logs /tmp/windmill/search /tmp/.cache && chmod 777 /tmp/.cache
|
|
|
|
# Make directories world-accessible for any UID
|
|
# (cache files already have 666 from umask copy above, cache_nomount is read-only)
|
|
RUN find ${APP} /tmp/windmill -type d -exec chmod 777 {} +
|
|
|
|
EXPOSE 8000
|
|
|
|
CMD ["windmill"]
|