首页 > 解决方案 > Dockerfile 和 Jenkinsfile - COPY 存储库

问题描述

我正在尝试在 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 文件夹,我需要分别复制所有创建的文件夹?

标签: dockerjenkinsdockerfile

解决方案


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

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

容器的主要运行进程是 Dockerfile 末尾的 ENTRYPOINT 和/或 CMD。通常建议您通过每个容器使用一项服务来分隔关注区域。该服务可能会分叉成多个进程(例如,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 在其文档中列出的另一个选项包括使用supervisordwhich 应该使用适当的配置处理您打算在容器中运行的所有主要进程,这里是如何配置它。请记住,它是要安装在您的容器或基础映像上的另一个软件包。

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


推荐阅读