Gitlab CI Registry变量配置问题:docker-compose运行报错排查
我在配置GitLab CI/CD时,按照要求把镜像名格式$CI_REGISTRY/organisation/path-to-project/project_image:$CI_ENVIRONMENT_SLUG-$CI_COMMIT_SHA写入.env文件的IMAGE_NAME变量。但执行docker compose up时,提示这些CI变量未设置,镜像格式无效。奇怪的是,.gitlab-ci.yml的before_script里docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY能正常使用这些变量。
报错信息
level=warning msg="The \"CI_REGISTRY\" variable is not set. Defaulting to a blank string." level=warning msg="The \"CI_ENVIRONMENT_SLUG\" variable is not set. Defaulting to a blank string." level=warning msg="The \"CI_COMMIT_SHA\" variable is not set. Defaulting to a blank string." Error response from daemon: no such image: organisation/path-to-project/project_image:-: invalid reference format
相关配置
.gitlab-ci.yml配置
image: docker/compose:alpine-1.28.0 stages: - build - deploy before_script: - apk add make - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - cp $ENV $(pwd)/src/.env build: stage: build script: - make build push tags: - job:build only: - main environment: name: production deploy: stage: deploy script: - make pull down migrate up tags: - job:deploy only: - main environment: name: production
注:
$ENV是GitLab上配置的变量。
docker-compose.yml配置
services: app1: build: . image: ${IMAGE_NAME} env_file: - .env # ... app2: build: . image: ${IMAGE_NAME} env_file: - .env # ...
核心原因
直接把包含CI变量的字符串写入.env文件是无效的——GitLab CI的变量仅在CI运行环境中生效,.env文件里的$CI_REGISTRY这类变量不会被CI自动解析替换。当Docker Compose读取.env时,这些变量在当前环境中不存在,会被替换为空字符串,最终导致镜像名格式错误。
解决步骤
方法1:动态生成.env文件
不要直接复制预先写好的.env文件,而是通过模板动态生成:
- 在代码仓库中保存.env模板文件(比如命名为
.env.template),内容用占位符代替CI变量:IMAGE_NAME={{CI_REGISTRY}}/organisation/path-to-project/project_image:{{CI_ENVIRONMENT_SLUG}}-{{CI_COMMIT_SHA}} # 其他环境变量... - 在.gitlab-ci.yml的before_script中,用
envsubst替换模板占位符生成实际.env:
CI运行时会自动将环境变量值填入占位符,生成正确的IMAGE_NAME。- envsubst < .env.template > $(pwd)/src/.env
方法2:直接给Docker Compose传入变量
跳过.env文件,在执行docker compose命令时直接注入变量:
修改deploy阶段的script命令:
- IMAGE_NAME="$CI_REGISTRY/organisation/path-to-project/project_image:$CI_ENVIRONMENT_SLUG-$CI_COMMIT_SHA" docker compose up -d
Docker Compose会直接使用CI环境中的变量值,无需读取.env。
方法3:通过makefile传递变量
如果依赖makefile执行构建/部署命令,在CI调用make时传入变量:
# build阶段 - make build push IMAGE_NAME="$CI_REGISTRY/organisation/path-to-project/project_image:$CI_ENVIRONMENT_SLUG-$CI_COMMIT_SHA" # deploy阶段 - make pull down migrate up IMAGE_NAME="$CI_REGISTRY/organisation/path-to-project/project_image:$CI_ENVIRONMENT_SLUG-$CI_COMMIT_SHA"
同时调整makefile中的对应命令,使用传入的IMAGE_NAME变量。
内容的提问来源于stack exchange,提问作者fgrd4035

