如何在GitLab CI的dock:dind中执行卷映射(装入卷)? [英] How can I do volume mapping (mounting volumes) in dock:dind in GitLab CI?

查看:21
本文介绍了如何在GitLab CI的dock:dind中执行卷映射(装入卷)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在GitLab CI中运行Selenium下载测试。我在gitLab-ci.yml文件中使用docker:dind。测试失败,因为没有真正下载的文件。我该怎么办?

测试脚本:

package seleniumTest;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class LoginTest_chrome_ci {
    WebDriver driver;
    File folder;

    @BeforeMethod
    public void setUp() throws  MalformedURLException {

        String directory = "/target";
        folder = new File(directory);

        System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
        ChromeOptions options = new ChromeOptions();

        Map<String, Object> prefs = new HashMap<String, Object>();
        prefs.put("profile.default_content_settings.popups", 0);
        prefs.put("download.prompt_for_download", "false");
        prefs.put("download.directory_upgrade", "true");
        prefs.put("download.default_directory", folder.getAbsolutePath());

        options.setExperimentalOption("prefs", prefs);
        DesiredCapabilities cap = new DesiredCapabilities();
        cap.setBrowserName("chrome");
        cap.setCapability(ChromeOptions.CAPABILITY, options);

        driver = new RemoteWebDriver(new URL("http://docker:4444/wd/hub"), cap);
    }

    @AfterMethod
    public void tearDown() {
        driver.quit();

    }

    @Test
    public void downloadFileTest() throws InterruptedException {
        driver.get("http://the-internet.herokuapp.com/download");
        driver.findElement(By.linkText("some-file.txt")).click();

        Thread.sleep(4000);

        File listOffFiles[] = folder.listFiles();

        System.out.println(listOffFiles.length);
        Assert.assertTrue(listOffFiles.length > 0);

        for(File file : listOffFiles) {
            Assert.assertTrue(file.length() > 0);
        }
    }
}

docker-compose文件中,我已经完成了Chrome容器的卷映射:

version: "3"
services:
  chrome:
    image: selenium/node-chrome:4.0.0-20211013
    container_name: chrome
    shm_size: 2gb
    depends_on:
      - selenium-hub
    volumes:
      - /target:/home/seluser/Downloads
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_GRID_URL=http://localhost:4444
    ports:
      - "6900:5900"
  selenium-hub:
    image: selenium/hub:4.0.0-20211013
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

我使用的gitlab-ci.yml文件是:

image: adoptopenjdk/openjdk11

stages:
  - gradle-build
  - docker-test

.gradle_template: &gradle_definition
  variables:
    GRADLE_OPTS: "-Dorg.gradle.daemon=false"
  before_script:
    - export GRADLE_USER_HOME=${CI_PROJECT_DIR}/.gradle

gradle-build:
  <<: *gradle_definition
  stage: gradle-build
  script:
    - chmod +x ./gradlew
    - ./gradlew --build-cache assemble
  cache:
    key: "$CI_COMMIT_REF_NAME"
    paths:
      - build
      - .gradle
  artifacts:
    paths:
      - build/libs/*.jar
    expire_in: 1 day
  only:
    - feature/multi-browsers

chrome-test:
  stage: docker-test
  image:
    name: docker/compose:1.29.2
    entrypoint: [ "/bin/sh", "-c" ]
  services:
    - docker:19.03.12-dind
  variables:
    DOCKER_TLS_CERTDIR: ""
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: tcp://docker:2375/
  cache:
    key: "$CI_COMMIT_REF_NAME"
    policy: pull
    paths:
      - build
      - .gradle
  dependencies:
    - gradle-build
  before_script:
    - docker info
    - docker-compose --version
  script:
    - apk add --no-cache docker-compose
    - apk add openjdk11
    - mkdir /target
    - chmod -R 777 /target
    - docker-compose down
    - docker-compose up --build --force-recreate --no-deps -d
    - echo "Hello, chrome-test"
    - chmod +x ./gradlew
    - ./gradlew :test --tests "LoginTest_chrome_ci"

  artifacts:
    when: always
    reports:
      junit: build/test-results/test/**/TEST-*.xml
    paths:
      - build/reports/*
    expire_in: 1 day
  only:
    - feature/multi-browsers

after_script:
  - echo "End CI"

我收到的错误是:

Gradle suite > Gradle test > seleniumTest.LoginTest_chrome_ci > downloadFileTest FAILED
    java.lang.AssertionError at LoginTest_chrome_ci.java:71

推荐答案

使用docker:dind服务时,带有docker-compose的卷映射或多或少会正常工作。

但是,我建议您在根目录中使用相对路径,而不是绝对路径。例如./target而不是/target

使用docker挂载目录:dind

作为可重现的最小示例:

获取以下合成文件:

version: "3"
services:
  test:
    image: busybox
    entrypoint: ["/bin/sh", "-c", "echo hello > /opt/data/foo.txt"]
    volumes:
      - ./target:/opt/data

这将创建单个容器,其装入点位于相对目录./target,并将其装入到容器中的/opt/data
当服务容器启动时,它只会创建一个文本为hello的文件/opt/data/foo.txt

和以下GitLab CI YAML:

test:
  image: docker/compose
  services:
    - docker:dind
  script:
    - ls # no target directory exists
    - docker-compose up
    - ls target  # target directory was created and foo.txt exists
    - cat ./target/foo.txt  # see the contents of foo.txt as "hello"

因此,您的错误一定是由于装入点未装入目录以外的其他原因造成的。

权限注意事项

文件/目录权限仍然适用于绑定装载。因此,容器中的用户需要拥有对挂载的目录/文件进行读/写的权限。

在这种情况下几乎肯定会遇到的问题是selenium/node-chrome:4.0.0-20211013停靠容器中的用户的UID/GID为1200/1201。因此,docker-compose在您的作业中为卷装载创建的目录将不会被容器中的用户写入。

例如,上面的相同最小示例--如果将映像从busybox(以root身份运行,与作业容器相同)更改为selenium/node-chrome:4.0.0-20211013,使用不同的用户UID/GID运行,则作业将失败,并显示";权限被拒绝";错误。

因此,可以得出结论,您的问题是Chrome无法写入~/Downloads目录,这就是您在下载目录中看不到文件的原因。

如何解决问题

若要解决此问题,应提前chown将挂载点创建到容器中用户的uid/gid。

所以有两件事:

  1. 将目录更改为./target,而不是/target(更新合成文件和代码)
  2. 在您的GitLab-CI作业中,请在启动docker-compose之前预先创建./targetchown 1200:1201 ./target

类似以下内容将解决权限问题:

before_script:
  - mkdir -p ./target
  - chown 1200:1201 ./target

这篇关于如何在GitLab CI的dock:dind中执行卷映射(装入卷)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆