GitLab CI中FastAPI容器启动后无法连接localhost的问题求助
GitLab CI中无法访问Docker容器内FastAPI服务的排查问题
测试GitLab CI时遇到问题:封装了Python FastAPI服务的容器镜像,本地Fedora笔记本运行正常,但在GitLab CI中,容器状态显示正常,却无法通过localhost:8080访问API,修改端口也无效。本人是GitLab新手,怀疑漏了基础配置细节,以下是相关信息及恳请排查建议。
关键信息摘要
- 本地运行容器正常,GitLab CI中运行失败
- GitLab CI中容器已启动,但Web服务器未被监听
- 修改端口尝试无效
CI运行输出
Status: Downloaded newer image for registry.gitlab.com/mygroup/myuser/dsaeventserver:dev registry.gitlab.com/mygroup/myuser/dsaeventserver:dev $ CTR_ID=$(docker run -d --name test_container -p 8080:80 $IMAGE_NAME) $ sleep 2 $ docker logs $CTR_ID INFO Using path src/swimming.py INFO Resolved absolute path /code/src/swimming.py INFO Searching for package file structure from directories with __init__.py files INFO Importing from /code/src ╭─ Python module file ─╮ │ │ │ 🐍 swimming.py │ │ │ ╰──────────────────────╯ INFO Importing module swimming INFO Found importable FastAPI app ╭── Importable FastAPI app ──╮ │ │ │ from swimming import app │ │ │ ╰────────────────────────────╯ INFO Using import string swimming:app ╭─────────── FastAPI CLI - Production mode ───────────╮ │ │ │ Serving at: http://0.0.0.0:80 │ │ │ │ API docs: http://0.0.0.0:80/docs │ │ │ │ Running in production mode, for development use: │ │ │ │ fastapi dev │ │ │ ╰─────────────────────────────────────────────────────╯ INFO: Started server process [1] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) $ sleep 10 $ docker image list REPOSITORY TAG IMAGE ID CREATED SIZE registry.gitlab.com/mygroup/myuser/dsaeventserver dev ff56e284a3eb About a minute ago 1.09GB $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5896fc35220b registry.gitlab.com/mygroup/myuser/dsaeventserver:dev "fastapi run src/swi…" 15 seconds ago Up 12 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp test_container $ netstat -ant | egrep -i "listen|established" Active Internet connections (servers and established) $ curl http://localhost:8080/docs % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 curl: (7) Failed to connect to localhost port 8080 after 0 ms: Could not connect to server Cleaning up project directory and file based variables 00:00 ERROR: Job failed: exit code 7
gitlab-ci.yml测试配置
job test: stage: test image: docker:latest variables: APP_PORT: "8080" before_script: - apk add --update curl && rm -rf /var/cache/apk/* services: - docker:dind script: # Log into the registry - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY # Pull the container image - docker pull $IMAGE_NAME # Run the container, aliasing port 80 to 8080 - CTR_ID=$(docker run -d --name test_container -p 8080:80 $IMAGE_NAME) - sleep 2 - docker logs $CTR_ID # Give the container some time to start up (optional, depending on the container) - sleep 10 # some debug. - docker image list - docker ps -a - netstat -ant | egrep -i "listen|established" # Use curl to check if the container is accessible on port 8080 - curl http://localhost:8080/docs - curl http://localhost:8080/swimmer
Dockerfile内容
# FROM python:3.12 # WORKDIR /code # COPY ./requirements.txt /code/requirements.txt # RUN pip install "fastapi[standard]" RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt # COPY ./src /code/src # CMD ["fastapi", "run", "src/swimming.py", "--port", "80"]
本地成功运行示例
$ docker run -d --name swimapi -p 8080:80 localhost/charmr 4f70955539c7cd4f48559e9345577c72ae3ca056aeab9435d437b7457e1830f4 $ curl http://127.0.0.1:8080/swimmer | head -1 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 22216 100 22216 0 0 1485k 0 --:--:-- --:--:-- --:--:-- 1549k [{"first_name":"David","family_name":"Davis","age":39,"swimming_stroke":"Breaststroke",... etc
排查建议
切换访问地址为docker服务主机名
在GitLab CI的Docker-in-Docker(DinD)环境中,你启动的容器运行在docker:dind服务容器内部,而非job的主容器(docker:latest)。直接用localhost访问的是主容器的网络,而非DinD容器的网络。需要把curl命令中的localhost换成docker(GitLab会自动给服务设置主机名):- curl http://docker:8080/docs - curl http://docker:8080/swimmer验证DinD网络连通性
可以在job脚本中添加以下命令,测试与DinD服务的连通性:- ping -c 3 docker - nc -zv docker 8080替换sleep为可靠的等待脚本
固定的sleep时间不一定能适配所有服务启动速度,建议安装wait-for-it脚本,等待端口就绪后再执行curl:before_script: - apk add --update curl wait-for-it && rm -rf /var/cache/apk/* script: # ... 其他命令 ... - wait-for-it docker:8080 -t 20 -- curl http://docker:8080/docs检查DinD的网络模式配置
若上述方法无效,可尝试在gitlab-ci.yml中为docker:dind服务添加network_mode: host配置(注意部分runner环境可能限制此配置):services: - name: docker:dind command: ["--network=host"]此时启动容器无需端口映射,直接访问
http://docker:80/docs即可。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

