目前我正在为NodeJS项目做DevOps。我正在使用Pm2作为nodejs进程管理器来部署应用程序,但我正在考虑切换到Docker。在这方面,我正在考虑部署应用程序的最佳部署策略。
首先我想在为应用程序创建一个docker镜像,然后在该图像中执行app更新任务。每次我们更新应用程序时都不需要创建另一个docker镜像。
但是,我认为第1号选项与微服务哲学直接冲突。所以我认为遵循微服务理念意味着每个应用程序更新都需要一个新的微服务版本,因此我们每次更新应用程序时都必须构建一个新的docker镜像版本。
我想知道什么是最适合您的方法,为什么以及使用什么工具来自动化部署过程中构建的新图像。
感谢。
答案 0 :(得分:1)
我倾向于组织Docker部署的方式如下:
docker/
base/
Dockerfile
build/
Dockerfile
Dockerfile
package.json
...
首先创建一个基本映像Docker映像,这包括构建和运行时共有的所有依赖项,以便在两个Docker映像之间重用这些层:
# docker/base/Dockerfile
FROM node:9.5-alpine
RUN apk --no-cache add ...
从基础Docker镜像中创建一个包含构建时特定工具和依赖项的构建Docker镜像,CMD触发构建过程:
# docker/build/Dockerfile
FROM app-base:1.0
RUN apk --no-cache add ...
VOLUME ["/var/workspace"]
WORKDIR /var/workspace
CMD ["npm", "install"]
然后,您可以通过在app-build
图像中运行应用程序来构建应用程序。我通常会输出一个tarball,其中包含所有已构建的依赖项,可以通过这种方式运行,将整个应用程序注入到新的Docker镜像中非常简单。
最后将应用程序打包到docker映像中,它只包含生产依赖项以及为运行应用程序而设置的用户和组,并将获取从构建步骤输出的tarball,即:
FROM app-base:1.0
ARG version=latest
ARG user=app
ARG uid=1000
ARG gid=1000
RUN apk --no-cache add ... && useradd ...
ADD app-${version}.tar.gz /usr/share/app
WORKDIR /usr/share/app
USER ${user}
CMD ["node", "/usr/share/app/index.js"]
我在Docker镜像中构建它,以便我不会引入不兼容性直接从主机构建它,并且我在生产图像中使用单独的Docker镜像,这样我的生产图像中没有额外的东西,这有助于减少传输Docker镜像时的大小,并减少表面区域的安全性。 YMMV,这只是一种方法。
我尚未调查multi-stage builds,但它看起来像一个有趣的选项。
<强>更新强>
我参与过的一些团队开始使用单个Docker镜像,该镜像具有一个入口点脚本,用于安装应用程序及其依赖项,但最终因为依赖于网络上的资源而不再存在(存储库已关闭)当他们需要部署关键变更时。
但是,我参与过的一些团队继续使用这种方法,因为他们认为Docker镜像不是主要的工件。他们的图像下载了打包的应用程序,配置和机密,他们确保所有依赖项都托管在其网络中的存储库及其控制之中。