我计划使用 Docker 部署一个 Node.js 应用程序。 该应用程序有几个需要node-gyp的依赖项。 Node-gyp 根据交付平台上的编译库构建这些模块(例如 canvas、lwip、qrcode),根据我的经验,这些构建可能高度依赖于操作系统版本和安装的库,并且它们经常破坏简单的 npm安装。
那么构建我的 Dockerfile FROM node:version 是正确的方法吗? 这似乎是我迄今为止找到的每个 Docker/Node 教程中展示的方法。 但如果我从节点镜像构建,部署容器时会发生什么? 如何确保目标主机具有编译 node-gyp 模块所需的库?
我正在考虑的另一种方法是构建 Dockerfile FROM ubuntu:version。 但我认为这意味着将 NodeJS 安装到 Ubuntu 镜像中,整个事情会更大。
还有其他方法可以处理这个问题吗?
如何确保目标主机具有编译node-gyp模块所需的库?
目标主机也正在运行 docker。只要依赖项存在于您的映像中,那么您的服务器也拥有它们。如果你问我的话,这就是 docker 的全部意义所在。如果它在本地运行,那么它也在服务器上运行。
对于更小的文件,我会选择 node-alpine (
FROM node:8-alpine
)。在我开始研究 Node-gyp 之前,我一直在努力解决它,但现在我什至不明白我怎么会认为这是一个问题。只要添加构建工具 RUN apk add python make gcc g++
就可以了(但这会增加 100-200mb 的大小)。
此外,如果它变得耗时(假设您发现自己时不时地使用 --no-cache 重建图像),那么最好将其分成您自己的基本图像和另一个图像
FROM my-base-image:latest
其中包含您经常更改的内容。
肯定有一些学习曲线,但我没有发现它那么陡峭。至少如果你以前接触过 docker 的话就不会。
我正在寻找的另一种方法是从 ubuntu:version 构建 Dockerfile。
在使用 docker 之前我只使用过 CentOS,并且我在我的服务器上运行 CentOS。所以我认为运行 CentOS 镜像也是个好主意,但我发现这很愚蠢。除非您需要特定于操作系统的东西,否则增益绝对为零。现在我只使用 alpine 大概半年了,到目前为止我唯一需要学习的 alpine 特定命令是
apk add/del
。
你可能已经知道了,但一开始不要花太多时间优化 docker 文件大小。 (您可以通过在一行上组合命令(添加包、运行命令、删除包)来大幅减少层大小。但是,如果您在大层中进行任何小的更改,这会取消 docker 镜像缓存的使用。最好离开直到事情变得重要为止。
如果您需要使用node-gyp构建东西,您可以添加下面的行,替换您的
npm install
或yarn install
:
RUN apk add --no-cache --virtual .build-deps make gcc g++ python3 \
RUN npm install --production --silent \
RUN apk del .build-deps
或者更简单,你可以安装
alpine-sdk
,类似于 Debian 的 build-essentials
RUN apk add --no-cache --virtual .build-deps alpine-sdk python3 \
RUN npm install --production --silent \
RUN apk del .build-deps
来源:https://github.com/mhart/alpine-node/issues/27#issuecomment-390187978
回顾过去(2年后),管理容器中的节点依赖关系仍然是一个挑战。 我现在做的是:
构建docker镜像FROM节点:10.16.0-alpine(或其他节点 版本)。 这些是 hub.docker.com 上的官方 node 图像。 码头工人 推荐 alpine,Nodejs 建立在其之上,包括 node-gyp,所以这是一个很好的起点;
包含 RUN apk add --no-cache 以包含所有库 需要构建依赖模块,例如画布(参见下面的示例);
在 docker 构建文件中包含 RUN npm install canvas;这 将节点模块(例如画布)构建到 docker image 中,因此它会加载到从该图像运行的任何容器中。
但这可能会变得丑陋。 Alpine 使用与更重量级操作系统不同的库:值得注意的是,alpine 使用 musl 代替 glibc。 依赖模块可能需要链接到 glibc,因此您必须将其添加到图像中。 Sasha Gerrand 提供了一种方法,使用 alpine-pkg-glibc
安装node-canvas v2.5的示例,链接到glibc:
# geo_core layer
# build on a node image, in turn built on alpine linux, Docker's official linux pulled from hub.docker.com
FROM node:10.16.0-alpine
# add libraries needed to build canvas
RUN apk add --no-cache \
build-base \
g++ \
libpng \
libpng-dev \
jpeg-dev \
pango-dev \
cairo-dev \
giflib-dev \
python \
; \
# add glibc and install canvas
RUN apk --no-cache add ca-certificates wget && \
wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.29-r0/glibc-2.29-r0.apk && \
apk add glibc-2.29-r0.apk && \
npm install [email protected]
;
2023年答案:
# Wont work with any version newer version of node
FROM --platform=linux/amd64 node:8-alpine
# Build dependencies
RUN apk add make gcc g++ python3
# Avoid "gyp ERR! stack Error: certificate has expired"
ENV NODE_TLS_REJECT_UNAUTHORIZED=0
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["sh"]