Docker容器构建后gRPC服务无法自动启动问题排查
问题描述
基于Python:3.6.2构建Docker容器,在Dockerfile中通过CMD命令python server/grpc_main.py & python main.py尝试同时启动gRPC服务与主程序,但gRPC服务无法自动运行,手动执行该命令则正常。
Dockerfile代码:
FROM python:3.6.2 COPY ./services/api/requirements.txt /myapp RUN pip install -r requirements.txt COPY . /myapp/src WORKDIR /myapp/src/services/api COPY ./.env /myapp CMD python server/grpc_main.py & python main.py
grpc_main.py代码:
def serve(mirza_server): """serve builds server :param mirza_server: an instance of mirza server :type mirza_server: MirzaServer """ server = grpc.server(futures.ThreadPoolExecutor(max_workers=200)) mirza_server_pb2_grpc.add_MirzaServicer_to_server(mirza_server, server) server.add_insecure_port('0.0.0.0:50051') server.start() server.wait_for_termination() @click.command() @click.option('--env', default='.env') def main(env='.env', boxes_path=None, genres_path=None, editorials=None): mod_path = Path(__file__).parent if boxes_path is None: boxes_path = mod_path / '../boxes.json' if genres_path is None: genres_path = mod_path / '../genres.json' if editorials is None: editorials = mod_path / '../editorials.json' binding_spec = MirzaBindingSpec(env, boxes_path, genres_path, editorials) obj_g = pinject.new_object_graph(binding_specs=[binding_spec], modules=[mirza, shared_utils]) server = obj_g.provide(MirzaServer) serve(server)
问题原因
Click库的终端依赖导致进程异常退出
grpc_main.py的主函数使用@click.command()装饰,当通过&将进程放到后台运行时,该进程会失去交互式终端环境,标准输入被关闭。Click库在初始化命令行解析逻辑时依赖终端上下文,没有终端会直接触发异常退出,导致gRPC服务无法启动。而手动执行时处于交互式终端,stdin/stdout正常,所以能正常运行。Docker进程管理机制导致后台进程被回收
Docker容器的生命周期与主进程绑定,当前CMD命令会启动一个shell作为容器主进程,grpc_main.py是该shell的后台子进程。一旦主进程(python main.py)或shell出现状态变化,后台的gRPC进程可能被Docker的init机制强制回收。另外,后台进程的输出未被正确捕获,可能因输出缓冲区溢出导致进程挂起退出。
内容的提问来源于stack exchange,提问作者Kia Lia
相关产品推荐
相关产品推荐

