GitLab CI使用容器仓库时提示docker: not found问题求助
错误原因分析
CI执行环境未预装Docker CLI
从错误日志可见,build_image任务使用Docker executor,默认拉取alpine:3.14作为执行环境镜像,该基础镜像未包含Docker CLI工具,因此执行docker build时会提示命令未找到。你在应用Dockerfile中添加的RUN apk add docker-cli是给最终构建的应用镜像安装Docker,和CI任务的执行环境完全无关。变量配置存在误解
你标注的变量对应关系错误:$CI_REGISTRY_IMAGE是GitLab自动生成的镜像仓库地址(如registry.gitlab.com/komorebi-cqd/mynodeapp-cicd-project),不是完整的docker build命令$CI_REGISTRY是仓库域名(如registry.gitlab.com),不是docker push命令
当前.gitlab-ci.yml中的变量定义本身没问题,但你的理解存在偏差。
Docker executor的隔离性限制
即使服务器本地安装了Docker,Docker executor默认会在独立容器中运行CI任务,容器无法直接访问主机的Docker命令,必须通过特定配置打破隔离。
具体解决方案
方案一:使用Docker-in-Docker(DinD)服务(官方推荐)
通过启动DinD服务,让CI任务的执行容器拥有完整的Docker环境,这是GitLab CI构建容器镜像的标准方案。
步骤1:修改.gitlab-ci.yml
更新build_image和push_image任务配置:
build_image: stage: build tags: - remoteone image: docker:24.0.6 # 使用包含Docker CLI的官方镜像 services: - docker:24.0.6-dind # 启动DinD服务 variables: DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: "/certs" DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client" before_script: - echo "Docker registry url is $CI_REGISTRY" - echo "Docker registry username is $CI_REGISTRY_USER" - echo "Docker registry repo is $CI_REGISTRY_IMAGE" - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker build -t $IMAGE_NAME . push_image: stage: build needs: - build_image tags: - remoteone image: docker:24.0.6 services: - docker:24.0.6-dind variables: DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: "/certs" DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client" script: - docker push $IMAGE_NAME
步骤2:开启Runner特权模式
DinD服务需要特权权限才能运行,修改Runner配置文件(通常为/etc/gitlab-runner/config.toml):
[[runners]] name = "one-docker-runner" url = "你的GitLab实例地址" token = "fAyvKeBR" executor = "docker" [runners.docker] tls_verify = false image = "alpine:3.14" privileged = true # 必须开启特权模式 disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = ["/cache"] shm_size = 0
步骤3:重启Runner
sudo gitlab-runner restart
方案二:改用Shell Executor
直接让CI任务在服务器本地执行,使用主机已安装的Docker环境,适合不需要容器化执行环境的场景。
步骤1:修改Runner配置
更新config.toml切换执行器:
[[runners]] name = "one-docker-runner" url = "你的GitLab实例地址" token = "fAyvKeBR" executor = "shell" # 改为shell执行器 [runners.cache] [runners.cache.s3] [runners.cache.gcs]
步骤2:重启Runner
sudo gitlab-runner restart
说明
无需修改.gitlab-ci.yml中的build_image和push_image任务,任务会直接调用主机的Docker命令执行。
方案三:挂载主机Docker Socket(不推荐,存在安全风险)
让CI执行容器共享主机的Docker服务,仅适合测试环境,因为会打破容器隔离性带来安全隐患。
修改.gitlab-ci.yml
build_image: stage: build tags: - remoteone image: alpine:3.14 variables: DOCKER_HOST: unix:///var/run/docker.sock before_script: - apk add --no-cache docker-cli # 在执行镜像中安装Docker CLI - echo "Docker registry url is $CI_REGISTRY" - echo "Docker registry username is $CI_REGISTRY_USER" - echo "Docker registry repo is $CI_REGISTRY_IMAGE" - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker build -t $IMAGE_NAME . volumes: - /var/run/docker.sock:/var/run/docker.sock # 挂载主机Docker Socket
修改Runner配置
允许挂载主机目录:
[[runners]] name = "one-docker-runner" url = "你的GitLab实例地址" token = "fAyvKeBR" executor = "docker" [runners.docker] tls_verify = false image = "alpine:3.14" privileged = false disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] shm_size = 0
内容的提问来源于stack exchange,提问作者qiaoda chen

