【问题标题】:Dockerfile and Jenkinsfile - COPY repositoryDockerfile 和 Jenkinsfile - COPY 存储库
【发布时间】:2021-09-07 10:27:23
【问题描述】:

我正在尝试在 Jenkinsfile 中克隆我所有的 git 存储库:

stage('Clone git') {
                          steps {sh 'mkdir repo1'
                                 sh 'cd repo1'
                                 dir ('repo1') {
                                 git ([url : 'https://github.../repo1.git', branch : 'develop', credentialsId : '***'])}

                                 sh 'mkdir repo2'
                                 sh 'cd repo2'
                                 dir ('repo2') {
                                 git ([url : 'https://github.../repo2.git', branch : 'develop', credentialsId : '***'])}
                      }
                  }

 stage('Build Docker') {
                      steps {sh 'cd ..'
                             sh 'docker build -t myimage .'
                             sh 'docker run myimage'
                      }

然后在我的 Dockerfile 中我有这个:

FROM node:12.2.0-alpine
COPY . /myapp
WORKDIR /myapp
RUN apk update

FROM gradle:6.3-jdk11 AS build
COPY --chown=gradle:gradle . /repo1
WORKDIR /repo1
RUN gradle build --no-daemon

WORKDIR /repo2
RUN npm install
RUN ng serve

请帮助我理解,如果我以正确的方式进行操作,特别是 COPY 命令。

我认为,它是这样工作的:首先它将 git repos 克隆到 repo1 和 repo2 文件夹。

然后在 Dockerfile 中它会在 myapp 文件夹中创建一个布局,它会复制 myapp 文件夹下的两个 repo 文件夹。

问题是,我需要同时运行这两个服务 - 在 repo1 中它是后端,需要构建 gradle,这就是为什么我将 gradle 复制到 repo1 文件夹,不确定是否应该在 COPY 中使用 myapp/repo1。

而repo2是前端,我认为不需要复制任何东西,只需选择WORKDIR repo2并运行服务器即可。

所以问题是,COPY 是否足够。 /myapp 在第一步中,它会复制那里的每个 repo 文件夹,还是只是将 docker 映像复制到 myapp 文件夹,我需要单独复制所有创建的文件夹?

【问题讨论】:

    标签: docker jenkins dockerfile


    【解决方案1】:

    当使用单个 Dockerfile 时,只能创建一个 docker 映像,因此如果您希望这两个服务都运行,您需要分别构建和运行它们(可能使用 -d 标志用于分离模式)。

    在同一个容器中使用多个应用程序 - docker docs

    容器的主要运行进程是 ENTRYPOINT 和/或 CMD Dockerfile 的结尾。一般建议分开 每个容器使用一项服务。该服务可能 fork 到多个进程(例如,Apache Web 服务器启动 多个工作进程)。可以有多个进程,但要 从 Docker 中获得最大收益,避免一个容器被 负责整个应用程序的多个方面。你可以 使用用户定义的网络连接多个容器并共享 卷。

    您可以创建一个脚本以在容器启动时运行,例如:

    #!/bin/bash
    
    # Start the first process
    ./my_first_process -D
    status=$?
    if [ $status -ne 0 ]; then
      echo "Failed to start my_first_process: $status"
      exit $status
    fi
    
    # Start the second process
    ./my_second_process -D
    status=$?
    if [ $status -ne 0 ]; then
      echo "Failed to start my_second_process: $status"
      exit $status
    fi
    
    # Naive check runs checks once a minute to see if either of the processes exited.
    # This illustrates part of the heavy lifting you need to do if you want to run
    # more than one service in a container. The container exits with an error
    # if it detects that either of the processes has exited.
    # Otherwise it loops forever, waking up every 60 seconds
    
    while sleep 60; do
      ps aux |grep my_first_process |grep -q -v grep
      PROCESS_1_STATUS=$?
      ps aux |grep my_second_process |grep -q -v grep
      PROCESS_2_STATUS=$?
      # If the greps above find anything, they exit with 0 status
      # If they are not both 0, then something is wrong
      if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
        echo "One of the processes has already exited."
        exit 1
      fi
    done
    

    然后让你的 CMD 命令像这样运行脚本:

    CMD ./my_wrapper_script.sh
    

    Docker 在其文档中列出的另一个选项包括使用supervisord,它应该通过适当的配置处理您打算在容器中运行的所有主要进程,here's 如何配置它。请记住,它是另一个要安装在您的容器或基础映像上的软件包。

    此外,由于节点不只是从默认目录静态地提供网站文件,您需要使用node 命令并指向应该定义节点网络服务器以提供诸如 express 或 http 之类的文件的父 JS 文件,请参阅this 示例。虽然如果你想使用生产网络服务器,你最好构建你的项目并使用像 nginx 或 apache http 这样的商业网络服务器,但你为他们构建项目(可能在 Dockerfile 中)将它们放在他们尊重的目录中并启动网络服务器进程,这是一个example

    【讨论】:

    • @Darksymphony 这个解决方案有帮助吗?
    【解决方案2】:

    如果您只是运行这两个应用程序,您可以将 Dockerfile 拆分为 2 个 Dockerfile,一个用于后端,一个用于前端,并在 docker-compose.yml 中引用它们

    docker-compose.yml 的示例:

    
    version: '3.9'
    services:
      backend:
        image: backend:${TAG:-latest}
        build:
          context: ./backend
          dockerfile: Dockerfile
    
      frontend:
        image: frontend:${TAG:-latest}
        build:
          context: ./frontend
          dockerfile: Dockerfile
    
    

    要使用 docker-compose 运行这两个服务,请执行 docker-compose up

    【讨论】:

    • 我无法创建 2 个 Dockerfile。 Jenkins 正在运行 Jenkinsfile,克隆前端和后端 git 存储库(我无法访问这些存储库来编辑任何内容),然后使用我的测试赛普拉斯存储库中的一个 Dockerfile。 Fe 和 BE 服务需要在一个 docker 容器中一起运行,因为它们相互依赖。在容器中运行之后,我需要在 Jenkins 的同一个容器中运行我的 cypress 测试
    • 请注意,Docker 容器不像虚拟机那样可以同时运行多个进程,您可以将其想象成单个进程执行。这意味着您不能在单个容器中运行这两个应用程序。我建议您编写这 2 个应用程序,以便它们之间只有网络依赖关系。如果你能做到这一点,你可以使用 docker-compose 解决方案或在这两个存储库中的每一个中放置一个 Dockerfile,并在 jenkins 的构建阶段为前端 repo 运行 docker build -t frontend . 并为后端 repo 运行 docker build -t backend .
    • @Darksymphony 您可以在 Dockerfile 上创建,但是启动您的应用程序、调试问题以及通常为两个主要进程调整容器的整个过程将只是一场噩梦。请再次考虑使用两个 Dockerfile
    • 好吧,应用程序正在服务器上运行 - 前端 angular 和 java 上的多个后端服务连接在一起。我想要实现的是在 Jenkins 中构建前端和后端(在 Kubernetes 上运行),然后在那里执行 cypress 测试。为此,我需要前端和后端运行。所有这些 repo 也已经包含它的 Dockerfile,但我认为还包括一个部署,所以我不能使用这些 Dockerfile,这就是为什么我在自己的 repo 中创建一个新的,它应该拉 FE 和 BE。我对 Docker 不是很熟悉,所以我会考虑你的建议。谢谢
    猜你喜欢
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-03-07
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    相关资源
    最近更新 更多