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

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

排查建议

  1. 切换访问地址为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
    
  2. 验证DinD网络连通性
    可以在job脚本中添加以下命令,测试与DinD服务的连通性:

    - ping -c 3 docker
    - nc -zv docker 8080
    
  3. 替换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
    
  4. 检查DinD的网络模式配置
    若上述方法无效,可尝试在gitlab-ci.yml中为docker:dind服务添加network_mode: host配置(注意部分runner环境可能限制此配置):

    services:
      - name: docker:dind
        command: ["--network=host"]
    

    此时启动容器无需端口映射,直接访问http://docker:80/docs即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:02:38