我的项目结构如下:
.
├── my_script.Dockerfile
├── README.rst
├── log
│ └── my_script.log
├── pickles
├── requirements.txt
├── requirements_my_script.txt
├── src
│ ├── __init__.py
│ ├── __pycache__
│ ├── main.py
│ ├── modules
│ │ ├── __init__.py
│ │ └── module.py
│ ├── other_scripts
│ │ └── my_script.py
│ └── utils
│ ├── __init__.py
│ ├── __pycache__
│ └── logging_utils.py
my_script.Dockerfile如下所示:
# syntax=docker/dockerfile:1
FROM python:3.10-slim-buster
WORKDIR /src
COPY requirements_my_script.txt requirements_my_script.txt
RUN pip3 install -r requirements_my_script.txt
COPY src/. .
CMD ["python3", "other_scripts/my_script.py"]
my_script.py:
import logging
from src.utils.logging_utils import start_logger
def main(logger):
# some code here
logger.info('done')
sleep(120)
if __name__=='__main__':
logger = start_logger('my_script.log')
try:
logger.info('Starting..')
main(logger)
except Exception as e:
logger.critical('Crashed with error: {}'.format(e))
和logging_utils.py:
import os
import logging
from logging.handlers import RotatingFileHandler
def start_logger(filename, level='INFO'): # INFO or DEBUG
# # LOGGING
log_folder = os.path.join(os.path.expanduser('~'), 'project_folder_name', 'log')
if not os.path.exists(log_folder):
os.makedirs(log_folder)
log_filename = filename
logger = logging.getLogger()
logFormatter = logging.Formatter(fmt='%(asctime)s :: %(levelname)s - %(message)s')
if level == 'DEBUG':
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
# add a rotating handler
handler = RotatingFileHandler(os.path.join(log_folder, log_filename), maxBytes=1000000, backupCount=1)
handler.setFormatter(logFormatter)
logger.addHandler(handler)
return logger
这在我的机器上运行得很完美,但当我构建docker并尝试运行它时,我会得到以下错误:
from src.utils.logging_utils import start_logger
ModuleNotFoundError: No module named 'src'
我在dockerfile中尝试了几个不同的COPY语句,但没有成功。
有人能告诉我我做错了什么吗?
编辑我也试过这个dockerfile:
# syntax=docker/dockerfile:1
FROM python:3.10-slim-buster
WORKDIR /app
COPY requirements_my_script.txt requirements_my_script.txt
RUN pip3 install -r requirements_my_script.txt
COPY src/ src/
CMD ["python3", "src/other_scripts/my_script.py"]
但我得到了完全相同的错误。
在不重构代码的情况下解决此问题的方法是在dockerfile中添加ENV,如下所示:
# syntax=docker/dockerfile:1
FROM python:3.10-slim-buster
WORKDIR /app
COPY requirements_my_script.txt requirements_my_script.txt
RUN pip3 install -r requirements_my_script.txt
COPY src/ src/
ENV PYTHONPATH /app
CMD ["python3", "src/other_scripts/my_script.py"]
从my_script.py
:中删除此行
from src.utils.logging_utils import start_logger
将这些行添加到my_script.py
:
from sys import path as syspath
from os import path as ospath
syspath.append(ospath.join(ospath.dirname(ospath.realpath(__file__)),'..','utils')) # To find out where to look, import the utils path into the script path
from logging_utils import start_logger
并在Dockerfile
:中执行此操作
COPY src/ src/
当您的代码执行import
时
from src.utils.logging_utils ...
Python查找相对于当前目录和Python搜索路径中的任何其他目录的./src/utils/logging_utils.py
。但在Dockerfile中,您去掉了src
目录:
COPY src/. .
将src
目录的内容复制到当前目录中。我猜如果您使用docker run --rm your-image ls
,您将立即在应用程序目录中看到utils
目录,而不是在src
子目录中。
如果您需要将主机上的子目录复制到映像中的子目录中,则需要在COPY
的两侧重复目录名,如
COPY src/ src/