diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml index d35a5ae178c..58861445cae 100644 --- a/.github/workflows/build-push.yml +++ b/.github/workflows/build-push.yml @@ -21,6 +21,7 @@ env: DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} DIFY_WEB_IMAGE_NAME: ${{ vars.DIFY_WEB_IMAGE_NAME || 'langgenius/dify-web' }} DIFY_API_IMAGE_NAME: ${{ vars.DIFY_API_IMAGE_NAME || 'langgenius/dify-api' }} + DIFY_AGENT_IMAGE_NAME: ${{ vars.DIFY_AGENT_IMAGE_NAME || 'langgenius/dify-agent-backend' }} jobs: build: @@ -60,6 +61,20 @@ jobs: file: "web/Dockerfile" platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 + - service_name: "build-agent-amd64" + image_name_env: "DIFY_AGENT_IMAGE_NAME" + artifact_context: "agent" + build_context: "{{defaultContext}}" + file: "dify-agent/Dockerfile" + platform: linux/amd64 + runs_on: depot-ubuntu-24.04-4 + - service_name: "build-agent-arm64" + image_name_env: "DIFY_AGENT_IMAGE_NAME" + artifact_context: "agent" + build_context: "{{defaultContext}}" + file: "dify-agent/Dockerfile" + platform: linux/arm64 + runs_on: depot-ubuntu-24.04-4 steps: - name: Prepare @@ -122,6 +137,9 @@ jobs: - service_name: "validate-web-amd64" build_context: "{{defaultContext}}" file: "web/Dockerfile" + - service_name: "validate-agent-amd64" + build_context: "{{defaultContext}}" + file: "dify-agent/Dockerfile" steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 @@ -147,6 +165,9 @@ jobs: - service_name: "merge-web-images" image_name_env: "DIFY_WEB_IMAGE_NAME" context: "web" + - service_name: "merge-agent-images" + image_name_env: "DIFY_AGENT_IMAGE_NAME" + context: "agent" steps: - name: Download digests uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 diff --git a/dify-agent/Dockerfile b/dify-agent/Dockerfile new file mode 100644 index 00000000000..6d56811981d --- /dev/null +++ b/dify-agent/Dockerfile @@ -0,0 +1,68 @@ +# Dedicated image for the standalone Dify Agent backend server. +# +# It is laid out to match how the service is deployed today (see the +# agent_backend compose service): the virtualenv lives at /app/api/.venv and +# the server is started with +# cd /app/api && .venv/bin/uvicorn dify_agent.server.app:app --host 0.0.0.0 --port 5050 +# +# Unlike the dify-api image (which only installs the base `dify-agent` +# dependency), this image installs the `[server]` extra, so jwcrypto, +# shell-session-manager, fastapi, uvicorn, etc. are present and the server can +# actually start. dify-api is intentionally left lean. + +# base image +FROM python:3.12-slim-bookworm AS base + +WORKDIR /app/api + +# Install uv +ENV UV_VERSION=0.8.9 + +RUN pip install --no-cache-dir uv==${UV_VERSION} + + +FROM base AS packages + +# The build context is the repository root (see build-push.yml), so paths are +# repo-root relative. dify-agent ships its own uv.lock that resolves the server +# extra, so this builds standalone without the api project. +COPY dify-agent/pyproject.toml dify-agent/uv.lock dify-agent/README.md ./ +COPY dify-agent/src ./src +# Trust the checked-in lock during image builds and install the server extra. +RUN uv sync --frozen --no-dev --no-editable --extra server + + +# production stage +FROM base AS production + +ENV TZ=UTC +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 +ENV PYTHONIOENCODING=utf-8 +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +WORKDIR /app/api + +# Create non-root user (uid matches the dify-api image convention) +ARG dify_uid=1001 +RUN groupadd -r -g ${dify_uid} dify && \ + useradd -r -u ${dify_uid} -g ${dify_uid} -s /bin/bash dify + +# Copy the resolved virtualenv. The dify-agent package is installed +# non-editable, so the source is already baked into site-packages. +ENV VIRTUAL_ENV=/app/api/.venv +COPY --from=packages --chown=dify:dify ${VIRTUAL_ENV} ${VIRTUAL_ENV} +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" + +# storage is bind-mounted at runtime; pre-create it so the dify user can write. +RUN mkdir -p /app/api/storage && chown -R dify:dify /app/api + +ARG COMMIT_SHA +ENV COMMIT_SHA=${COMMIT_SHA} + +EXPOSE 5050 + +USER dify + +CMD ["uvicorn", "dify_agent.server.app:app", "--host", "0.0.0.0", "--port", "5050"]