You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker镜像部署单节点Elasticsearch后curl连接被拒问题求助

Docker构建镜像时Elasticsearch启动后无法访问的问题解决

问题描述

尝试构建包含本地单节点Elasticsearch实例的Docker镜像,计划容器启动后完成:

  • 启动Elasticsearch实例
  • 通过Python脚本创建索引并加载文档
  • 通过Flask服务提供索引查询能力

但构建镜像时执行elasticsearch-8.6.0/bin/elasticsearch -d后,执行curl localhost:9200返回000连接被拒;注释掉启动ES的命令构建镜像后,手动进入容器执行相同启动命令,curl可正常返回200。

现有Dockerfile

FROM ubuntu:latest

SHELL ["/bin/bash", "-c"]
RUN apt-get -y update && apt-get install -y --no-install-recommends \
         sudo \
         wget \
         gnupg \
         curl \
         unzip \
         tar \
         ca-certificates \
         lsb-release \
         python3-pip \
         python3-setuptools \
         nginx \
    && rm -rf /var/lib/apt/lists/*

#setup elasticsearch
RUN wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.6.0-linux-aarch64.tar.gz
RUN tar -xzvf elasticsearch-8.6.0-linux-aarch64.tar.gz

##create a new user and give es permissions to it to start a node
RUN useradd es_user
RUN chown es_user:es_user -R elasticsearch-8.6.0
USER es_user
RUN echo "discovery.type: single-node" >> elasticsearch-8.6.0/config/elasticsearch.yml
RUN echo "xpack.security.enabled: false" >> elasticsearch-8.6.0/config/elasticsearch.yml
#RUN echo "network.host: 0.0.0.0" >> elasticsearch-8.6.0/config/elasticsearch.yml
#RUN echo "http.port: 9200" >> elasticsearch-8.6.0/config/elasticsearch.yml
#RUN echo "http.host: 0.0.0.0" >> elasticsearch-8.6.0/config/elasticsearch.yml
RUN  elasticsearch-8.6.0/bin/elasticsearch -d
RUN sleep 30
RUN echo $(curl -s -w '%{http_code}' localhost:9200)

构建日志curl输出

#18 [15/15] RUN echo $(curl -s -w '%{http_code}' localhost:9200)
#18 sha256:94cb4cd9486b0bf9a80c77c7648ba19ab373c3f8ec8e1131b3d68a0a55e0b268
#18 0.182 000
#18 DONE 0.2s

手动进入容器测试结果

{ "name" : "5bced6805917", "cluster_name" : "elasticsearch", "cluster_uuid" : "IAcnbmcfTmC84MjI3Y-jiA", "version" : { "number" : "8.6.0", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "f67ef2df40237445caa70e2fef79471cc608d70d", "build_date" : "2023-01-04T09:35:21.782467981Z", "build_snapshot" : false, "lucene_version" : "9.4.2", "minimum_wire_compatibility_version" : "7.17.0", "minimum_index_compatibility_version" : "7.0.0" }, "tagline" : "You Know, for Search" }
200

问题原因

Docker的RUN指令是在独立的临时容器层中执行的,每个RUN步骤结束后,该层的所有进程都会被终止,不会保留到后续的RUN步骤中。因此,在RUN elasticsearch-8.6.0/bin/elasticsearch -d启动的ES进程,会在该步骤执行完成后被销毁,下一个RUN步骤的环境中没有运行的ES实例,自然无法通过curl访问。

而手动进入容器时,所有操作都在同一个容器进程环境中,ES启动后会持续运行,因此curl可以正常访问。

解决方案

将服务启动逻辑从构建阶段(RUN)转移到容器启动阶段,使用ENTRYPOINT或CMD执行启动脚本,步骤如下:

1. 创建启动脚本start.sh

#!/bin/bash

# 启动Elasticsearch后台运行
elasticsearch-8.6.0/bin/elasticsearch -d

# 等待Elasticsearch完全启动(替代固定sleep,更可靠)
until curl -s localhost:9200 > /dev/null; do
  echo "等待Elasticsearch启动..."
  sleep 5
done

# 执行Python脚本创建索引并加载文档(替换为你的脚本路径)
python3 /app/create_index.py

# 启动Flask服务(确保Flask监听0.0.0.0,允许外部访问)
flask run --host=0.0.0.0 --port=5000

2. 修改Dockerfile

FROM ubuntu:latest

SHELL ["/bin/bash", "-c"]
RUN apt-get -y update && apt-get install -y --no-install-recommends \
         wget \
         curl \
         tar \
         ca-certificates \
         python3-pip \
         python3-setuptools \
    && rm -rf /var/lib/apt/lists/*

# 安装Elasticsearch
RUN wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.6.0-linux-aarch64.tar.gz
RUN tar -xzvf elasticsearch-8.6.0-linux-aarch64.tar.gz && rm elasticsearch-8.6.0-linux-aarch64.tar.gz

# 创建ES用户并配置权限
RUN useradd es_user
RUN chown es_user:es_user -R elasticsearch-8.6.0

# 配置Elasticsearch
USER es_user
RUN echo "discovery.type: single-node" >> elasticsearch-8.6.0/config/elasticsearch.yml
RUN echo "xpack.security.enabled: false" >> elasticsearch-8.6.0/config/elasticsearch.yml
RUN echo "network.host: 0.0.0.0" >> elasticsearch-8.6.0/config/elasticsearch.yml  # 允许容器外部访问

# 复制启动脚本和Python代码(假设你的脚本在当前目录的app文件夹下)
USER root
COPY start.sh /start.sh
COPY app /app
RUN chmod +x /start.sh && chown es_user:es_user -R /app
USER es_user

# 容器启动时执行脚本
CMD ["/bin/bash", "/start.sh"]

关键修改点

  • 移除构建阶段启动ES和curl的RUN指令,只保留环境准备和配置步骤
  • 添加启动脚本,将ES启动、Python脚本执行、Flask启动逻辑放到容器启动时执行
  • 启用network.host: 0.0.0.0,确保容器外部可以访问ES(如果不需要可注释)
  • 使用until循环替代固定sleep,等待ES完全启动后再执行后续操作,避免因启动慢导致的失败

内容的提问来源于stack exchange,提问作者armen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:45:34