【问题标题】:How to execute a command from a docker image in a gitlab job?如何从 gitlab 作业中的 docker 映像执行命令?
【发布时间】:2021-07-22 07:00:17
【问题描述】:

我创建了一个存储 npm 项目的 docker 映像。 npm 项目有一个运行测试的 npm 脚本。我将Gitlab 用于 CI/CD,我想在其中定义一个作业,该作业将提取我的图像并运行 npm 脚本。这是.gitlab.yml

stages:
  - test

.test-api:
  image: $CI_REGISTRY_IMAGE
  stage: test
  script:
    - cd packages/mypackage && npm run test:ci
  artifacts:
    paths:
      - packages/mypackage/test-report.html
    expire_in: 1 week

test-api-beta:
  extends: .test-api
  environment:
    name: some-env
  variables:
    CI_REGISTRY_IMAGE: my_image_name

gitlab 作业失败并出现错误:

> mypackage@1.0.0 test:ci /builds/my-organization/my-project/packages/mypackage
> DEBUG=jest-mongodb:* NODE_ENV=test ts-node --transpile-only --log-error node_modules/.bin/jest --watchAll=false --detectOpenHandles --bail
sh: 1: ts-node: not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! mypackage@1.0.0 test:ci: `DEBUG=jest-mongodb:* NODE_ENV=test ts-node --transpile-only --log-error node_modules/.bin/jest --watchAll=false --detectOpenHandles --bail`
npm ERR! spawn ENOENT
npm ERR! 
npm ERR! Failed at the mypackage@1.0.0 test:ci script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?
npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-04-28T09_05_39_023Z-debug.log

主要问题是错误npm WARN Local package.json exists, but node_modules missing, did you mean to install?。这意味着 gitlab script 在我项目的实际 git 存储库上执行,而不是在 docker 映像上执行。事实上,我的存储库不包含node_modules,因此作业失败。但是gitlab为什么不对实际图片执行script呢?

docker 镜像有一个CMD 指令: CMD ["npm", "run", "start"]

也许CMD 以某种方式干扰了 gitlab script

附:手动拉取 docker 镜像并在本地执行 npm 脚本。

这是我的Dockerfile

FROM node:14.15.1
COPY ./package.json /src/package.json

WORKDIR /src
RUN npm install
COPY ./lerna.json /src/lerna.json
COPY ./packages/mypackage/package.json /src/packages/mypackage/package.json
RUN npm run clean
COPY . /src
EXPOSE 8082
CMD ["npm" , "run", "start"]

编辑:根据 M. Iduoad answer 如果脚本更改如下:

.test-api:
  image: $CI_REGISTRY_IMAGE
  stage: test
  script:
    - cd /src/packages/mypackage && npm run test:ci
  artifacts:
    paths:
      - packages/mypackage/test-report.html
    expire_in: 1 week

npm 脚本有效。我们需要cd /src/packages/mypackage,因为这是 Dockerfile 中脚本的位置。

【问题讨论】:

    标签: docker gitlab continuous-integration gitlab-ci continuous-deployment


    【解决方案1】:

    Gitlab 总是克隆你的 repo 并检查你触发管道的分支并在该代码上运行你的命令(同一文件夹 CI_PROJECT_DIR

    因此,为了使用您的代码版本,您应该移动到它位于 docker 映像中的文件夹。

    .test-api:
      image: $CI_REGISTRY_IMAGE
      stage: test
      script:
        - cd /the/absolute/path/of/the/project/ && npm run test:ci
    

    这样做,违背了 gitlab-ci 的做事方式。由于每次运行 gitlab 作业时,您的作业将始终在相同的代码(图像中的代码)上运行。当 gitlab-ci 是一个 CI 系统并且旨在针对您的 git repo 中的代码运行作业时。

    总而言之,我建议您添加一个安装依赖项(node_modules)的阶段

    stages:
      - install
      - test
    
    install-deps:
      image: node:latest # or the version you are using
      stage: install
      script: 
        - npm install
      cache:
        key: some-key
        paths:
          - $CI_PROJECT_DIR/node_modules
    .test-api:
      image: $CI_REGISTRY_IMAGE
      stage: test
      script:
        - npm run test:ci
      cache:
        key: some-key
        paths:
          - $CI_PROJECT_DIR/node_modules
      artifacts:
        paths:
          - packages/mypackage/test-report.html
        expire_in: 1 week
    

    这将使用 gitlab-ci 的缓存功能,在您的作业和管道中存储 node_module。 您可以通过更改密钥来控制如何跨管道和作业使用和共享缓存。 (在gitlab's docs 上阅读有关缓存的更多信息)

    【讨论】:

    • 我已经在脚本/builds/my-organization/my-project/packages/mypackage 中访问了这个路径,但它不起作用。我应该访问什么路径才能让 docker 工作?
    • 默认情况下,您的项目(您在 gitlab 存储库中的代码)将位于 /builds/my-organization/my-project/packages/mypackage。如果您想访问您的 docker 映像中的版本,请查看您何时将其添加到您的 Dockerfile 中。正如我在答案中所说,尽量不要将代码复制到图像中并使用 repo 中的代码。
    • 确实在执行cd /src/packages/mypackage && npm run test:ci/src/packages/mypackage 是脚本在 docker 中的位置)之后,脚本工作了。但是 gitlab 如何确定我指的是 gitlan runner 还是 docker 中的路径?有这方面的文件吗?
    • 如果路径是绝对路径(以 `/' 开头),那么命令是否在 docker 容器中执行,否则它会在 gitlab runner 文件系统的项目目录中执行?除了this 之外,我找不到任何关于此的文档,其中写着“运行程序将脚本发送到容器的外壳标准输入并接收输出。”。但如果跑步者确实将脚本发送到容器的外壳,我的脚本就可以工作了。
    • Gitlab 运行者总是使用/builds/org/project/ 目录。他们在那里克隆你的仓库并针对它执行你的脚本。这是在 gitlab ci 中推荐的做事方式,并且在所有 CI/CD 工具中都很常见。我不知道您的具体用例,以及为什么拥有自定义 docker 映像对您很重要。但我认为大多数情况下官方的节点镜像都能胜任。
    猜你喜欢
    • 1970-01-01
    • 2021-11-14
    • 2022-01-04
    • 1970-01-01
    • 2023-03-26
    • 2020-06-28
    • 2017-10-27
    • 2017-10-18
    • 2021-09-17
    相关资源
    最近更新 更多