简体   繁体   English

从Docker容器内部读取rsync文件?

[英]rsync files from inside a docker container?

We are using Docker for the build/deploy of a NodeJS app. 我们正在使用Docker来构建/部署NodeJS应用程序。 We have a test container that is built by Jenkins, and executes our unit tests. 我们有一个由詹金斯(Jenkins)构建的test容器,并执行我们的单元测试。 The Dockerfile looks like this: Dockerfile看起来像这样:

FROM node:boron

# <snip> some misc unimportant config here

# Run the tests
ENTRYPOINT npm test

I would like to modify this step so that we run npm run test:cov , which runs the unit tests + generates a coverage report HTML file. 我想修改此步骤,以便我们运行npm run test:cov ,它运行单元测试+生成覆盖率报告HTML文件。 I've modified the Dockerfile to say: 我已经将Dockerfile修改为:

# Run the tests + generate coverage
ENTRYPOINT npm run test:cov

... which works. ...有效。 Yay! 好极了!

...But now I'm unsure how to rsync the coverage report ( generated by the above command inside the Dockerfile ) to a remote server. ......但现在我不知道该如何rsync覆盖报告(由Dockerfile内的上述命令生成)到远程服务器。

In Jenkins, the above config is invoked this way: 在Jenkins中,上述配置是通过以下方式调用的:

docker run -t test --rm

which, again, runs the above test and exists the container. 再次运行上述测试并存在该容器。

how can I add some additional steps after the entrypoint command executes, to (for example) rsync some results out to a remote server? 在entrypoint命令执行后,如何添加一些其他步骤,以(例如)将一些结果同步到远程服务器?

Make a script to execute as the entrypoint and put the commands in the script. 使脚本作为入口点执行,然后将命令放入脚本中。 You pass in args when calling docker run and they get passed to the script. 您在调用docker run时传递了args,它们被传递给了脚本。

The docs have an example of the postgres image's script. 该文档有一个postgres图片脚本示例。 You can build off that. 您可以以此为基础。

Docker Entrypoint Docs Docker Entrypoint文档

I am not a "node" expert, so bear with me on the details. 我不是“节点”专家,所以请多多包涵。

First of all, you may consider if you need a separate Dockerfile for running the tests. 首先,您可能会考虑是否需要单独的Dockerfile来运行测试。 Ideally, you'd want your image to be built, then tested, without modifying the actual image. 理想情况下,您希望在不修改实际图像的情况下构建,测试图像。

Building a test-image that uses your NodeJS app as a base image ( FROM my-nodejs-image ) could do the trick, but may not be needed if all you have to do is run a different command / entrypoint on the image. 构建一个使用NodeJS应用程序作为基本映像的测试映像( FROM my-nodejs-image )可以解决问题,但是如果您要做的只是在映像上运行不同的命令 / 入口点 ,则可能不需要这样做。

Secondly; 其次; stateful data (the coverage report falls into that category) should not be stored inside the container (ie, not stored on the container's filesystem). 状态数据(覆盖率报告属于该类别)不应存储在容器内(即,不存储在容器的文件系统上)。 You want your containers to be ephemeral, and anything that should live beyond the container's lifecycle (anything that should be preserved after the container itself is gone), should be stored outside of the container; 您希望您的容器是临时的,并且应该在容器的生命周期之外生存的所有内容(在容器自身消失之后应保留的所有内容)都应存储在容器外部 either in a "volume", or in a bind-mounted directory. 在“卷”中或在绑定安装的目录中。

Let me start with the "separate Dockerfile" point. 让我从“单独的Dockerfile”开始。 Let's say, your NodeJS application Dockerfile looks like this; 假设您的Dockerfile应用程序Dockerfile如下所示;

FROM node:boron

COPY package.json /usr/src/app/
RUN npm install && npm cache clean
COPY . /usr/src/app

CMD [ "npm", "start" ]

You build your image, and tag it, for example, with the commit it was built from; 您可以构建图像并对其进行标记,例如,使用图像的构建来源进行标记;

docker build -t myapp:$GIT_COMMIT .

Once the image was built succesfully, you want to test it. 成功构建映像后,您要对其进行测试。 Probably a quick test to verify it actually "runs". 可能是一项快速测试,以验证它是否确实在“运行”。 Many ways to do that, perhaps something like; 有很多方法可以做到这一点,例如:

docker run \
  -d \
  --rm \
  --network=test-network \
  --name test-{$GIT_COMMIT} \
  myapp:$GIT_COMMIT

And a container to test it actually does something; 一个用于测试它的容器实际上可以执行某些操作;

docker run --rm --network=test-network my-test-image curl test-{$GIT_COMMIT}

Once tested (and the temporary container removed), you can run your coverage tests, however, instead of writing the coverage report inside the container, write it to a volume or bind-mount. 一旦测试(并删除了临时容器),就可以运行覆盖率测试,但是,与其将覆盖率报告写入容器内部,也可以将其写入卷或绑定挂载,而不必将其写入容器中。 You can override the command to run in the container with docker run ; 您可以使用docker run 覆盖要在容器中运行的命令;

mkdir -p /coverage-reports/{$GIT_COMMIT}
docker run \
  --rm \
  --name test-{$GIT_COMMIT}\
  -v /coverage-reports/{$GIT_COMMIT}:/usr/src/app/coverage \
  myapp:$GIT_COMMIT npm run test:cov

The commands above; 上面的命令;

  • Create a unique local directory to store the test-artifacts (coverage report) 创建一个唯一的本地目录来存储测试工件(覆盖率报告)
  • Runs the image you built (and tagged myapp:$GIT_COMMIT ) 运行您构建的图像(并标记为myapp:$GIT_COMMIT
  • Bind-mount the /coverage-reports/{$GIT_COMMIT} into the container at usr/src/app/coverage /coverage-reports/{$GIT_COMMIT}绑定安装到位于usr/src/app/coverage的容器中
  • Runs the coverage tests (which will write to /usr/src/app/coverage if I'm not mistaken - again, not a Node expert) 运行覆盖率测试(如果我没记错的话,它将写入/usr/src/app/coverage再次,不是Node专家)
  • Removes the container once it exits 退出容器后将其取出

After the container exits, the coverage report is stored in /coverage-reports/{$GIT_COMMIT} on the host. 容器退出后,覆盖率报告将存储在主机上的/coverage-reports/{$GIT_COMMIT} You can use your regular tools to rsync those where you want. 您可以使用常规工具将它们rsync到所需的位置。

As an alternative, you can use a volume plugin to write the results to (eg) an s3 bucket, which saves you from having to rsync the results. 作为替代方案,您可以使用卷插件将结果写入(例如) s3存储桶中,从而不必重新同步结果。

Once tests are successful, you can docker tag the image to bump your application's version (eg docker tag myapp:1.0.12345 ), docker push to your registry, and deploy the new version. 测试成功后,您可以docker tag映像以更改应用程序的版本(例如docker tag myapp:1.0.12345 ), docker tag myapp:1.0.12345 docker push送到注册表,并部署新版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM