运行 Grunt / Gulp 在 Docker 容器内还是在容器外?
Run Grunt / Gulp inside Docker container or outside?
我正在尝试确定使用 grunt/gulp 部署在 docker 容器内的 nodejs 应用程序构建过程的良好实践。
我对以下顺序非常满意:
- 在容器外使用 g运行t(或 gulp)构建
- 将 ./dist 文件夹添加到容器
- 运行 在容器内安装 npm(带有 --production 标志)
但在我发现的每个示例中,我都看到了不同的方法:
- 将 ./src 文件夹添加到容器
- 运行 在容器内安装 npm(具有开发依赖项)
- 运行 在容器内安装 bower(如果需要)
- 运行 g运行t (or gulp) inside container
IMO,第一种方法生成更轻、更高效的容器,但所有示例都使用第二种方法。我错过了什么吗?
我看到的唯一区别是您可以在第二种方法中重现完整的 grunt 安装。
对于第一个,您依赖于可能在不同环境中以不同方式完成的本地操作。
容器应该基于可以轻松复制的图像,而不是依赖于包含 "what is needed" 的主机文件夹(不知道该部分是如何完成的)
如果安装附带的构建环境开销对于 grunt 映像来说太多了,您可以:
- 创建专用于安装的映像“
app.tar
”(I did that for Apache, that I had to recompile, creating a deb package in a shared volume)。
在您的情况下,您可以创建已安装应用程序的存档 ('tar')。
使用第一个容器中的卷从基本映像创建容器
docker run --it --name=app.inst --volumes-from=app.tar ubuntu untar /shared/path/app.tar
docker commit app.inst app
然后最终结果是应用程序存在于其文件系统上的图像。
这是方法 1 和方法 2 的混合。
我想推荐第三种方法,即我为静态生成的网站所做的,即单独的构建图像。
在这种方法中,您的主要 Dockerfile
(项目根目录中的那个)成为构建和开发映像,基本上在第二种方法中完成所有操作。但是,您在 运行 时覆盖 CMD
,即将 tar 构建的 dist
文件夹放入 dist.tar
或类似文件夹。
然后,您有另一个文件夹(类似于 image
),其中包含 Dockerfile
。这张图片的作用只是服务于dist.tar
的内容。所以我们做一个docker cp <container_id_from_tar_run> /dist
。然后 Dockerfile
只安装我们的网络服务器并有一个 ADD dist.tar /var/www
。
摘要是这样的:
- 构建
builder
Docker 图像(这将为您提供一个没有网络服务器的工作环境)。此时,应用程序已构建。我们可以 运行 使用 grunt serve
开发中的容器,或者使用任何命令来 tar 构建我们的内置开发服务器。
- 代替 运行 连接服务器,我们将默认命令覆盖到 tar 我们的 dist 文件夹。像
tar -cf /dist.tar /myapp/dist
. 这样的东西
- 我们现在有一个带有
/dist.tar
工件的临时容器。使用 docker cp <container_id_from_tar_run> /dist.tar ./image/
. 将其复制到我们称为 image
的实际部署 Docker 文件夹
- 现在,我们可以构建小型 Docker 图像,而无需使用
docker build ./image
的所有开发依赖项。
我喜欢这种方法,因为它仍然是所有 Docker。这种方法中的所有命令都是 Docker 命令,您可以真正精简最终部署的实际映像。
如果您想使用这种方法查看图像,请查看 https://github.com/gliderlabs/docker-alpine,它使用构建器图像(在构建器文件夹中)构建 tar.gz 文件,然后将其复制到他们各自的 Dockerfile
文件夹。
解决方案 1 的一个变体是 "parent -> child",这使得项目的构建非常快。
我会有 docker 文件,如:
FROM node
RUN mkdir app
COPY dist/package.json app/package.json
WORKDIR app
RUN npm install
这将处理节点依赖项的安装,并有另一个 docker 文件来处理应用程序 "installation",例如:
FROM image-with-dependencies:v1
ENV NODE_ENV=prod
EXPOSE 9001
COPY dist .
ENTRYPOINT ["npm", "start"]
这样您就可以继续您的开发,并且 docker 映像的 "build" 将比您需要 "re-install" 节点依赖项时更快。如果您在节点上安装新的依赖项,只需重新构建依赖项映像即可。
我希望这对某人有所帮助。
此致
我正在尝试确定使用 grunt/gulp 部署在 docker 容器内的 nodejs 应用程序构建过程的良好实践。
我对以下顺序非常满意:
- 在容器外使用 g运行t(或 gulp)构建
- 将 ./dist 文件夹添加到容器
- 运行 在容器内安装 npm(带有 --production 标志)
但在我发现的每个示例中,我都看到了不同的方法:
- 将 ./src 文件夹添加到容器
- 运行 在容器内安装 npm(具有开发依赖项)
- 运行 在容器内安装 bower(如果需要)
- 运行 g运行t (or gulp) inside container
IMO,第一种方法生成更轻、更高效的容器,但所有示例都使用第二种方法。我错过了什么吗?
我看到的唯一区别是您可以在第二种方法中重现完整的 grunt 安装。
对于第一个,您依赖于可能在不同环境中以不同方式完成的本地操作。
容器应该基于可以轻松复制的图像,而不是依赖于包含 "what is needed" 的主机文件夹(不知道该部分是如何完成的)
如果安装附带的构建环境开销对于 grunt 映像来说太多了,您可以:
- 创建专用于安装的映像“
app.tar
”(I did that for Apache, that I had to recompile, creating a deb package in a shared volume)。
在您的情况下,您可以创建已安装应用程序的存档 ('tar')。 使用第一个容器中的卷从基本映像创建容器
docker run --it --name=app.inst --volumes-from=app.tar ubuntu untar /shared/path/app.tar docker commit app.inst app
然后最终结果是应用程序存在于其文件系统上的图像。
这是方法 1 和方法 2 的混合。
我想推荐第三种方法,即我为静态生成的网站所做的,即单独的构建图像。
在这种方法中,您的主要 Dockerfile
(项目根目录中的那个)成为构建和开发映像,基本上在第二种方法中完成所有操作。但是,您在 运行 时覆盖 CMD
,即将 tar 构建的 dist
文件夹放入 dist.tar
或类似文件夹。
然后,您有另一个文件夹(类似于 image
),其中包含 Dockerfile
。这张图片的作用只是服务于dist.tar
的内容。所以我们做一个docker cp <container_id_from_tar_run> /dist
。然后 Dockerfile
只安装我们的网络服务器并有一个 ADD dist.tar /var/www
。
摘要是这样的:
- 构建
builder
Docker 图像(这将为您提供一个没有网络服务器的工作环境)。此时,应用程序已构建。我们可以 运行 使用grunt serve
开发中的容器,或者使用任何命令来 tar 构建我们的内置开发服务器。 - 代替 运行 连接服务器,我们将默认命令覆盖到 tar 我们的 dist 文件夹。像
tar -cf /dist.tar /myapp/dist
. 这样的东西
- 我们现在有一个带有
/dist.tar
工件的临时容器。使用docker cp <container_id_from_tar_run> /dist.tar ./image/
. 将其复制到我们称为 - 现在,我们可以构建小型 Docker 图像,而无需使用
docker build ./image
的所有开发依赖项。
image
的实际部署 Docker 文件夹
我喜欢这种方法,因为它仍然是所有 Docker。这种方法中的所有命令都是 Docker 命令,您可以真正精简最终部署的实际映像。
如果您想使用这种方法查看图像,请查看 https://github.com/gliderlabs/docker-alpine,它使用构建器图像(在构建器文件夹中)构建 tar.gz 文件,然后将其复制到他们各自的 Dockerfile
文件夹。
解决方案 1 的一个变体是 "parent -> child",这使得项目的构建非常快。 我会有 docker 文件,如:
FROM node
RUN mkdir app
COPY dist/package.json app/package.json
WORKDIR app
RUN npm install
这将处理节点依赖项的安装,并有另一个 docker 文件来处理应用程序 "installation",例如:
FROM image-with-dependencies:v1
ENV NODE_ENV=prod
EXPOSE 9001
COPY dist .
ENTRYPOINT ["npm", "start"]
这样您就可以继续您的开发,并且 docker 映像的 "build" 将比您需要 "re-install" 节点依赖项时更快。如果您在节点上安装新的依赖项,只需重新构建依赖项映像即可。
我希望这对某人有所帮助。
此致