首页 > 解决方案 > Docker 中的 Flask:Dockerfile build 和 docker-compose 中的不同相对导入

问题描述

我有一个具有以下结构的简单 Flask 应用程序:

|__app     
|  └── __init__.py
|  └── config.py
└── docker-compose.yml
└── Dockerfile

这里的关键是__init__.pyimport config.py。我使用 docker-compose 在容器中以 DEBUG 模式运行应用程序,而最终产品是仅从 Dockerfile 构建的容器。

__init__.py文件:

from flask import Flask

from .config import config


def create_app(config_name='development'):
    """Create the app."""
    app = Flask(__name__)
    app.config.from_object(config[config_name])

    @app.route('/', methods=['GET'])
    def index():
        return 'hello world' 

    return app

Dockerfiledocker 容器中构建应用程序:

FROM python:3.6-alpine
COPY requirements.txt /
RUN pip install Flask gunicorn
COPY app/ /app
WORKDIR /app
EXPOSE 8000
CMD gunicorn --bind=0.0.0.0:8000 "__init__:create_app()"

docker-compose.yml用于开发:它共享应用程序目录,因此它使应用程序能够在调试模式下运行:

version: '3'
services:
  svc1:
    build: .
    entrypoint:
      - flask
      - run
      - --host=0.0.0.0
    environment:
      FLASK_DEBUG: 1
      FLASK_APP: __init__.py
    ports: ['5000:5000']
    volumes: ['./app:/app']

在主文件夹中,您可以在调试模式下运行应用程序,docker-compose up --build -d然后导航到 localhost:5000 它返回“hello world”。

但是,如果您使用它构建图像docker build -t exampleapi .并运行它会抱怨:

模块中的文件“/app/ init .py”,第 3 行

从 .config 导入配置

ImportError:尝试在没有已知父包的情况下进行相对导入

标签: pythondocker-composedockerfile

解决方案


如此处所述,为了使相对导入工作,更简单的选项之一是将模块的全点名称指定给 Gunicorn,如下所示:

app.__init__.create_app()

使这项工作的其他选择包括:

  • 将您的相对导入更改为类似from mymodule import as_int. 这仅在您的模块名称是唯一的情况下才有效。否则,您可以:

  • from mypackage.mymodule import as_int


推荐阅读