我有一个 monorepo (
turbo
),其中包含多个应用程序,其中一个是 Python 应用程序。我已经为应用程序设置了 Dockerfile,但在构建过程中遇到了问题。
这是我的 Dockerfile:
FROM node:19.9.0-alpine as base
# adding apk deps to avoid node-gyp related errors and some other stuff. adds turborepo globally
RUN apk add -f --update --no-cache --virtual .gyp nano bash libc6-compat g++ \
&& yarn global add turbo \
&& apk del .gyp
RUN apk --no-cache add make python3 py3-pip
#############################################
FROM base AS pruned
WORKDIR /app
ARG APP
COPY . .
# see https://turbo.build/repo/docs/reference/command-line-reference#turbo-prune---scopetarget
RUN turbo prune --scope=sheet_sync --docker
#############################################
FROM base AS installer
WORKDIR /app
ARG APP
COPY --from=pruned /app/out/json/ .
COPY --from=pruned /app/out/yarn.lock /app/yarn.lock
# Forces the layer to recreate if the app's package.json changes
COPY services/sheet-sync/package.json /app/services/sheet-sync/package.json
# see https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#run---mounttypecache
RUN \
--mount=type=cache,target=/usr/local/share/.cache/yarn/v6,sharing=locked \
yarn --prefer-offline --frozen-lockfile
COPY --from=pruned /app/out/full/ .
COPY turbo.json turbo.json
# For example: `--filter=frontend^...` means all of frontend's dependencies will be built, but not the frontend app itself (which we don't need to do for dev environment)
RUN turbo run build --no-cache --filter=sheet_sync^...
# re-running yarn ensures that dependencies between workspaces are linked correctly
RUN \
--mount=type=cache,target=/usr/local/share/.cache/yarn/v6,sharing=locked \
yarn --prefer-offline --frozen-lockfile
#############################################
FROM base AS runner
WORKDIR /app
COPY --from=installer /app .
CMD yarn workspace sheet_sync start
这是我的 package.json 的相关部分:
{
"name": "sheet_sync",
"version": "0.0.1",
"scripts": {
"start": "make run",
"debug": "make debug",
"build": "make build"
}
}
还有我的 Makefile:
.PHONY: test
test:
pytest -svv -s
.PHONY: build
build:
python3 -m venv googleSheetENV
source googleSheetENV/bin/activate && python3 -m pip install -r requirements.txt
.PHONY: run
run:
python3 main.py
问题出现在Docker构建过程中,错误信息如下:
yarn workspace v1.22.19
yarn run v1.22.19
$ make run
python3 main.py
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
info Visit https://yarnpkg.com/en/docs/cli/workspace for documentation about this command.
Traceback (most recent call last):
File "/app/services/sheet-sync/main.py", line 1, in <module>
from src.reads.supplier_info import build as build_supliers
File "/app/services/sheet-sync/src/reads/supplier_info.py", line 1, in <module>
from src.reads.read_data_from_sheet import read_data_from_sheet
File "/app/services/sheet-sync/src/reads/read_data_from_sheet.py", line 1, in <module>
from src.config.google_config import sheets
File "/app/services/sheet-sync/src/config/google_config.py", line 2, in <module>
from dotenv import load_dotenv
ModuleNotFoundError: No module named 'dotenv'
make: *** [Makefile:12: run] Error 1
error Command failed with exit code 2.
error Command failed.
Exit code: 2
Command: /usr/local/bin/node
Arguments: /opt/yarn-v1.22.19/lib/cli.js start
Directory: /app/services/sheet-sync
Output:
需求.txt
absl-py==1.4.0
annotated-types==0.6.0
anyio==3.7.1
aws-lambda-powertools==2.19.0
beautifulsoup4==4.12.2
black==23.3.0
blinker==1.6.3
build==0.10.0
cachetools==5.3.1
certifi==2023.7.22
charset-normalizer==3.3.0
click==8.1.7
colorama==0.4.6
dnspython==2.4.2
fastapi==0.103.2
filelock==3.12.4
fire==0.5.0
flake8==6.0.0
Flask==3.0.0
Flask-Cors==3.0.10
gdown==4.7.1
google-api-core==2.12.0
google-api-python-client==2.101.0
google-auth==2.23.2
google-auth-httplib2==0.1.1
google-auth-oauthlib==1.1.0
googleapis-common-protos==1.60.0
grpc-google-iam-v1==0.12.6
grpcio==1.56.2
grpcio-status==1.56.2
gspread==5.11.3
gspread-formatting==1.1.2
gunicorn==21.2.0
h11==0.14.0
httplib2==0.22.0
idna==3.4
imageio==2.31.5
iniconfig==2.0.0
isort==5.12.0
itsdangerous==2.1.2
Jinja2==3.1.2
lazy_loader==0.3
markdown-it-py==3.0.0
MarkupSafe==2.1.3
mccabe==0.7.0
mdurl==0.1.2
mypy==1.4.1
mypy-extensions==1.0.0
networkx==3.1
numpy==1.26.0
oauthlib==3.2.2
opencv-python==4.8.1.78
opencv-python-headless==4.8.1.78
ortools==9.6.2534
packaging==23.2
pathspec==0.11.1
Pillow==10.0.1
platformdirs==3.8.1
pluggy==1.3.0
proto-plus==1.22.3
protobuf==4.24.3
pyasn1==0.5.0
pyasn1-modules==0.3.0
pycodestyle==2.10.0
pydantic==2.4.2
pydantic_core==2.10.1
pyflakes==3.0.1
Pygments==2.16.1
pymongo==4.6.1
pyparsing==3.1.1
pyproject_hooks==1.0.0
PySocks==1.7.1
pytest==7.4.2
python-dotenv==0.19.0
pytz==2023.3.post1
PyYAML==6.0.1
requests==2.31.0
requests-oauthlib==1.3.1
rich==13.6.0
rsa==4.9
scikit-image==0.22.0
scipy==1.11.3
six==1.16.0
sniffio==1.3.0
soupsieve==2.5
starlette==0.27.0
tabulate==0.9.0
termcolor==2.3.0
tifffile==2023.9.26
tqdm==4.66.1
typing_extensions==4.8.0
uritemplate==4.1.1
urllib3==2.0.6
uvicorn==0.23.2
Werkzeug==3.0.0
我怀疑该问题与 Docker 构建过程或必要库的潜在错误安装有关,特别是在构建过程中缺少 dotenv 模块,即使它存在于我的 Python 代码中。
我已经尝试在我的requirements.txt中包含python-dotenv,但问题仍然存在。
dotenv
不在您的要求中。txt
在您的 Makefile 中,
build
目标正在使用虚拟环境,但 run
目标则不是。这会导致您看到的错误。
如果您想保留现有系统,您应该确保在任何地方一致使用虚拟环境。我建议使用 Make 的标准依赖系统来确保“虚拟环境存在”和“软件包已安装”之类的事情:它是一个构建协调系统,而不仅仅是一个脚本运行程序。
# Location of the virtual environment
VIRTUAL_ENV := googleSheetENV
# Python executable inside the virtual environment
PYTHON := $(VIRTUAL_ENV)/bin/python3
# Test runner; something installed by requirements.txt
PYTEST := $(VIRTUAL_ENV)/bin/pytest
# Artificial build targets
.PHONY: dependencies build test run
all: run
dependencies: $(PYTEST)
build: dependencies
# Create the virtual environment using the system Python
$(PYTHON):
python3 -m venv $(VIRTUAL_ENV)
# Install dependencies, hinging on an arbitrary binary known to exist
$(PYTEST): requirements.txt $(PYTHON)
$(PYTHON) -m pip install $<
# Run tests
test: $(PYTEST)
$(PYTEST) -svv -s
# Run the application
run: $(PYTEST)
$(PYTHON) main.py
向后遍历:最后,
make run
运行$(PYTHON)/main.py
,它使用Python的虚拟环境副本。它取决于 $(PYTEST)
,它运行 pip install
步骤,而这又取决于 $(PYTHON)
,它最初创建虚拟环境。 Make 依赖项意味着,如果您再次make run
(在非容器环境中),它不会重复初始安装步骤。
如果这对于“在容器中运行 Python 应用程序”来说看起来很复杂,那么事实确实如此。您的设置使用 Javascript 构建管理器来调用 C 构建管理器来调用 Python 构建系统。此外,Docker 镜像已经是一个隔离的环境,并且该镜像的“系统”Python 与任何可能存在的其他 Python 是隔离的;大多数情况下,您不需要 Docker 中的虚拟环境。
您的设置可能还有其他 Javascript 部分,但对于这个应用程序,我将使用例程 Python Dockerfile
FROM python:3.12
WORKDIR /app
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY ./ ./
CMD ["/app/main.py"]
并丢弃 Makefile 和 Javascript
package.json
。
您需要在与 Javascript 组件不同的容器中运行它,并使用单独的图像。不过,这可能没问题,而且您已经需要运行多个容器,因为容器只运行一个程序。