本地正常的Django测试在GitHub Actions中执行失败求助
问题背景
本地执行docker compose run --rm app sh -c "python manage.py wait_for_db && python manage.py test"正常,但在GitHub Actions的Ubuntu-24.04环境中执行时出现Segmentation fault (core dumped),退出码139;尝试改用docker-compose命令时提示未知命令。
可能原因及解决方案
1. 确认Docker Compose命令格式
Ubuntu-24.04环境预装的是Docker Engine v25+,使用的是**docker compose(空格分隔)**的新命令格式,旧版的docker-compose(连字符)已被弃用,所以出现"未知命令"是正常的,继续使用docker compose即可。
2. 排查段错误(Exit Code 139)的常见原因
段错误通常由内存访问违规导致,针对Django+Docker场景,可从以下方向排查:
(1) 镜像架构不兼容
如果本地是ARM64架构(比如M系列Mac),而GitHub Actions使用AMD64架构,若镜像未构建为多架构版本,可能引发运行时错误。
- 解决方案:
- 确保Docker镜像支持多架构(比如通过Docker Hub自动构建勾选多架构,或用
docker buildx构建); - 在GitHub Actions的命令中显式指定架构:
docker compose run --rm --platform linux/amd64 app sh -c "python manage.py wait_for_db && python manage.py test"
- 确保Docker镜像支持多架构(比如通过Docker Hub自动构建勾选多架构,或用
(2) Python依赖或版本冲突
部分Python包在特定环境下存在兼容性问题,可能触发段错误。
- 解决方案:
- 检查
requirements.txt或pyproject.toml中的依赖版本,确保与Ubuntu-24.04环境的Python版本匹配; - 在测试前强制更新依赖:
docker compose run --rm app sh -c "pip install --upgrade pip && pip install -r requirements.txt && python manage.py wait_for_db && python manage.py test"
- 检查
(3) wait_for_db脚本逻辑问题
自定义的wait_for_db命令若存在无限循环、资源泄漏等逻辑缺陷,可能导致内存溢出触发段错误。
- 解决方案:
- 简化并加固脚本逻辑,添加超时机制:
import time from django.db import connections from django.db.utils import OperationalError from django.core.management.base import BaseCommand class Command(BaseCommand): def handle(self, *args, **options): self.stdout.write('Waiting for database...') db_conn = None timeout = 30 start_time = time.time() while not db_conn and (time.time() - start_time) < timeout: try: db_conn = connections['default'] db_conn.ensure_connection() except OperationalError: self.stdout.write('Database unavailable, waiting 1 second...') time.sleep(1) if not db_conn: self.stdout.write(self.style.ERROR('Database connection timeout!')) exit(1) self.stdout.write(self.style.SUCCESS('Database available!'))
- 简化并加固脚本逻辑,添加超时机制:
(4) GitHub Actions资源限制
GitHub Actions默认虚拟机资源有限,若测试用例占用过多内存,可能触发段错误。
- 解决方案:
- 优化测试用例,减少内存占用;
- 在工作流中配置更大的资源类:
jobs: test-lint: name: Test and Lint runs-on: ubuntu-24.04 resource-class: large # 可选xlarge,根据需求选择 # ... 其余步骤不变
(5) 基础镜像问题
若使用的Python基础镜像(如python:3.x-slim)存在已知的段错误问题,可更换镜像版本。
- 解决方案:
- 尝试使用更稳定的基础镜像,比如
python:3.12-bookworm替代python:3.12-slim; - 确保基础镜像已更新到最新补丁版本。
- 尝试使用更稳定的基础镜像,比如
调试建议
在GitHub Actions的测试步骤中添加调试命令,获取更详细的错误栈信息:
- name: Test with Debug run: | docker compose run --rm app sh -c " python -V && pip list && python manage.py wait_for_db && python -X faulthandler manage.py test "
python -X faulthandler会在段错误时输出详细的栈跟踪,帮助定位具体出错位置。
内容的提问来源于stack exchange,提问作者The Bat

