在Dockerfile中开发依赖项,还是为生产和测试分别使用单独的Dockerfile?

13

我不确定是否应该为我的Node.js应用程序创建不同的Dockerfile文件,一个文件用于生产环境,不包含开发依赖项,另一个文件用于测试,包含开发依赖项。

或者只使用一个开发Dockerfile.dev文件,两个文件的主要区别在于npm安装命令:

生产环境:

FROM ...
...
RUN npm install --quiet --production
...
CMD ...

开发/测试:

FROM ...
...
RUN npm install
...
CMD ...

我提出这个问题是因为我希望可以通过docker run命令在容器内运行我的测试。因此,我需要测试依赖项(通常是我需要的开发依赖项)。

将不需要在生产环境中使用的依赖项放入镜像中似乎有点奇怪。另一方面,创建/维护一个仅有微小差别的第二个Dockerfile.dev 也不太合适。那么,对于这种问题,有什么好的做法呢?


我只想说这里有所有的Docker文档,但是没有涉及测试。https://docs.docker.com/search/?q=test - William Entriken
2个回答

8
不需要使用不同的Dockerfile,实际上你应该避免这样做。Docker的目标是将你的应用程序作为一个不可变、经过充分测试的构件(docker镜像)进行发布,在生产环境、测试环境和开发环境中都是相同的。为什么?因为如果你为测试和生产构建不同的构件,如何保证你已经测试过的内容在生产环境中也能正常工作呢?你无法做到这一点,因为它们是两个不同的东西。鉴于这一点,如果你的测试是指单元测试,那么你可以将源代码挂载到docker容器中运行测试,而不需要构建任何docker镜像。这是可以接受的。请记住,你可以为测试构建镜像,但这会使开发变得非常困难和缓慢,这是完全不好的。然后,如果你的测试通过了,你可以安全地构建应用程序容器。但是,如果你的测试需要在正在运行的应用程序上运行,那么你应该为你的应用程序创建一个镜像(只有一个),并在另一个容器中运行测试(例如挂载测试源代码),并对该容器运行测试。这显然意味着你为应用程序构建的内容与npm安装的内容不同。我希望这可以给你一些概述。

谢谢你的回答。我想我明白了你的意思。我的问题是如何将测试源代码及其依赖项注入到包含生产/应用程序代码的镜像中。因此,在我的具体情况下,我可以将node_modules(测试依赖项)和测试源代码挂载到容器中,该容器包含应用程序。我可以考虑使用docker-compose配置文件来设置这个。这种方法的缺点是我的测试将依赖于我注入到容器中的依赖项,而不是生产中使用的依赖项。 - kgalli
看起来还不错,Docker和所有的进程都是相对较新的,只要你对这些进程感到舒适,并且在最后不会产生多个构件,那就应该没问题。请保持头脑清醒,随着时间的推移寻找新的解决方案和实践,因为事情会变得更加成熟。 - Boynux
顺便提一下,我正在使用我所解释的程序来进行生产应用,并且它运行得非常好。 - Boynux
我不喜欢这个。在生产环境中测试代码总是一个坏主意,可能会导致安全问题。我创建了一个测试Docker文件,以生产镜像为基础镜像+测试文件+mocha,并覆盖CMD到mocha。效果很好! - nahsh

2
那么你将不得不支持几个几乎相同的 Dockerfile。相反,我建议使用 NodeJS 的特性,如 生产配置文件。另外一个建议是关于
RUN npm install --quiet --production

最好创建一个单独的.sh文件,并像这样执行操作:
ADD ./scripts/run.sh /run.sh
RUN chmod +x /*.sh

还要考虑开始使用Gulp

更新 #1

默认情况下,npm install会安装devDependencies。为了避免这种情况,请使用npm install --production或将NODE_ENV环境变量设置为production值。

将脚本行放在单独的文件中是一个好习惯,以避免经常更改Dockerfile。如果您下次需要更改,则只需更新脚本文件即可完成。将来您可能还需要做一些其他工作。


谢谢你的回答。你能否更详细地描述一下像生产配置文件这样的功能如何帮助我。我还是会有两个文件,对吗?关于你的第二条建议:你建议将特定于环境的行放入脚本中并在构建时运行吗? - kgalli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接