dify-api的Dockerfile分析

一.dify-api的Dockerfile文件

dify-api的Dockerfile文件如下所示:

markdown 复制代码
# base image
FROM python:3.10-slim-bookworm AS base

LABEL maintainer="takatost@gmail.com"

# install packages
FROM base as packages

RUN apt-get update \
    && apt-get install -y --no-install-recommends gcc g++ libc-dev libffi-dev libgmp-dev libmpfr-dev libmpc-dev

COPY requirements.txt /requirements.txt

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --prefix=/pkg -r requirements.txt

# production stage
FROM base AS production

ENV FLASK_APP app.py
ENV EDITION SELF_HOSTED
ENV DEPLOY_ENV PRODUCTION
ENV CONSOLE_API_URL http://127.0.0.1:5001
ENV CONSOLE_WEB_URL http://127.0.0.1:3000
ENV SERVICE_API_URL http://127.0.0.1:5001
ENV APP_WEB_URL http://127.0.0.1:3000

EXPOSE 5001

# set timezone
ENV TZ UTC

WORKDIR /app/api

RUN apt-get update \
    && apt-get install -y --no-install-recommends curl wget vim nodejs ffmpeg libgmp-dev libmpfr-dev libmpc-dev \
    && apt-get autoremove \
    && rm -rf /var/lib/apt/lists/*

COPY --from=packages /pkg /usr/local
COPY . /app/api/

COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ARG COMMIT_SHA
ENV COMMIT_SHA ${COMMIT_SHA}

ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

二.Dockerfile文件分析

这个 Dockerfile 设计用于构建基于 Python 的 Flask 应用。将逐行解释这个文件:

1.基础镜像阶段

dockerfile 复制代码
FROM python:3.10-slim-bookworm AS base
LABEL maintainer="takatost@gmail.com"
  • FROM python:3.10-slim-bookworm AS base :这一行设置了基础镜像为 Python 3.10 版本的 slim 版本,基于 Debian bookworm。这种镜像较小,适合生产环境使用。并将此阶段命名为 base

  • LABEL maintainer="takatost@gmail.com":给镜像添加维护者的标签,方便联系和识别。

2.安装依赖包阶段

dockerfile 复制代码
FROM base as packages

RUN apt-get update \
    && apt-get install -y --no-install-recommends gcc g++ libc-dev libffi-dev libgmp-dev libmpfr-dev libmpc-dev

COPY requirements.txt /requirements.txt

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --prefix=/pkg -r requirements.txt
  • FROM base as packages :从基础镜像 base 开始新的构建阶段,命名为 packages

  • RUN apt-get update...:安装 Python 应用构建和运行时可能需要的系统依赖包,包括编译器和库文件。

  • COPY requirements.txt /requirements.txt :复制包含 Python 依赖的 requirements.txt 文件到容器中。

  • RUN --mount=type=cache,target=/root/.cache/pip...:利用 Docker 的构建缓存特性,安装 requirements.txt 中列出的 Python 依赖到 /pkg 目录,以提高后续构建的速度。

3.生产阶段设置

dockerfile 复制代码
FROM base AS production

ENV FLASK_APP app.py
...
EXPOSE 5001
...
WORKDIR /app/api

RUN apt-get update \
    && apt-get install -y --no-install-recommends curl wget vim nodejs ffmpeg libgmp-dev libmpfr-dev libmpc-dev \
    && apt-get autoremove \
    && rm -rf /var/lib/apt/lists/*

COPY --from=packages /pkg /usr/local
COPY . /app/api/

COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ARG COMMIT_SHA
ENV COMMIT_SHA ${COMMIT_SHA}

ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
  • FROM base AS production :从基础镜像 base 开始新的构建阶段,命名为 production

  • ENV FLASK_APP app.py 和其他 ENV:设置 Flask 环境变量和其他运行时环境变量。

  • EXPOSE 5001:声明容器将在端口 5001 上运行服务。

  • WORKDIR /app/api:设置工作目录。

  • RUN apt-get update...:更新包索引并安装生产环境所需的其他系统依赖,最后清理不再需要的包和临时文件。

  • COPY --from=packages /pkg /usr/local :从 packages 阶段复制安装好的 Python 依赖。

  • COPY . /app/api/:复制当前目录下所有文件到工作目录。

  • COPY docker/entrypoint.sh /entrypoint.sh:复制入口脚本到容器。

  • RUN chmod +x /entrypoint.sh:赋予入口脚本执行权限。

  • ARG COMMIT_SHAENV COMMIT_SHA ${COMMIT_SHA}:接收并设置构建参数,用于标记版本。

  • ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]:设置容器启动时执行的命令。

整个 Dockerfile 的设计旨在确保从依赖安装到应用部署的每个步骤都优化和安全,同时也支持构建缓存以加速多次构建过程。

三.dify\api\docker\entrypoint.sh文件分析

markdown 复制代码
#!/bin/bash

set -e

if [[ "${MIGRATION_ENABLED}" == "true" ]]; then
  echo "Running migrations"
  flask db upgrade
fi

if [[ "${MODE}" == "worker" ]]; then
  celery -A app.celery worker -P ${CELERY_WORKER_CLASS:-gevent} -c ${CELERY_WORKER_AMOUNT:-1} --loglevel INFO \
    -Q ${CELERY_QUEUES:-dataset,generation,mail}
elif [[ "${MODE}" == "beat" ]]; then
  celery -A app.celery beat --loglevel INFO
else
  if [[ "${DEBUG}" == "true" ]]; then
    flask run --host=${DIFY_BIND_ADDRESS:-0.0.0.0} --port=${DIFY_PORT:-5001} --debug
  else
    gunicorn \
      --bind "${DIFY_BIND_ADDRESS:-0.0.0.0}:${DIFY_PORT:-5001}" \
      --workers ${SERVER_WORKER_AMOUNT:-1} \
      --worker-class ${SERVER_WORKER_CLASS:-gevent} \
      --timeout ${GUNICORN_TIMEOUT:-200} \
      --preload \
      app:app
  fi
fi

这是一个 Bash 脚本,通常用于容器入口点(entrypoint)来启动 Flask 应用及相关服务。以下是脚本中每一行代码的中文解释:

bash 复制代码
#!/bin/bash
  • 这一行是 Shebang 行,指示操作系统使用 Bash 解释器执行此脚本。
bash 复制代码
set -e
  • 这一行设置了 Bash 的 -e 选项,意味着如果脚本中任何命令执行失败(返回非零状态),脚本将立即退出。
bash 复制代码
if [[ "${MIGRATION_ENABLED}" == "true" ]]; then
  echo "Running migrations"
  flask db upgrade
fi
  • 这个 if 语句检查环境变量 MIGRATION_ENABLED 是否设置为 "true"。如果是,执行数据库迁移命令 flask db upgrade,并在执行前打印 "Running migrations"。
bash 复制代码
if [[ "${MODE}" == "worker" ]]; then
  celery -A app.celery worker -P ${CELERY_WORKER_CLASS:-gevent} -c ${CELERY_WORKER_AMOUNT:-1} --loglevel INFO \
    -Q ${CELERY_QUEUES:-dataset,generation,mail}
elif [[ "${MODE}" == "beat" ]]; then
  celery -A app.celery beat --loglevel INFO
  • 这段代码根据环境变量 MODE 的值启动 Celery。如果 MODE"worker",则启动 Celery worker,并配置相关的选项(如并发方式、日志级别等)。如果 MODE"beat",则启动 Celery beat 进程。
bash 复制代码
else
  if [[ "${DEBUG}" == "true" ]]; then
    flask run --host=${DIFY_BIND_ADDRESS:-0.0.0.0} --port=${DIFY_PORT:-5001} --debug
  else
    gunicorn \
      --bind "${DIFY_BIND_ADDRESS:-0.0.0.0}:${DIFY_PORT:-5001}" \
      --workers ${SERVER_WORKER_AMOUNT:-1} \
      --worker-class ${SERVER_WORKER_CLASS:-gevent} \
      --timeout ${GUNICORN_TIMEOUT:-200} \
      --preload \
      app:app
  fi
fi
  • 这部分代码决定如何启动 Flask 应用。如果 DEBUG 环境变量被设置为 "true",则使用 Flask 的开发服务器启动应用。否则,使用 Gunicorn 作为 WSGI HTTP 服务器来运行应用,配置包括绑定的 IP 和端口、工作进程数量、工作进程类型、超时设置等。

整体上,这个脚本提供了灵活的启动配置,使得根据不同的环境需求(开发、生产、任务执行等)可以灵活地启动相应的服务。

相关推荐
小柒xq7 小时前
使用docker compose安装部署gitlab
docker·容器·gitlab
努力的小陈^O^7 小时前
docker学习笔记跟常用命令总结
java·笔记·docker·云原生
童先生7 小时前
如何将java项目打包成docker 镜像并且可运行
java·开发语言·docker
猿java10 小时前
Docker是什么?Kubernetes又是什么?如何通过代码实战理解它们?
java·docker·kubernetes
吃苹果的牛顿顿10 小时前
Docker本地搭建WordPress
运维·docker·容器
daizikui14 小时前
docker使用阿里云容器镜像服务下载公共镜像
阿里云·docker·容器
lu云之东15 小时前
Harbor2.11.1生成自签证和配置HTTPS访问
网络协议·http·docker·https·harbor
yangshuo128116 小时前
Docker-Compose 快速部署安装 Nginx 或其他应用
运维·nginx·docker
Eternal-Student16 小时前
【docker了解】如何将x86镜像转换为适用于Jetson的ARM镜像
arm开发·docker·容器
飘散风中17 小时前
Docker+PostgreSQL数据库
数据库·docker·容器