将 Docker 与具有 Node-gyp 依赖项的 Nodejs 一起使用

问题描述 投票:0回答:4

我计划使用 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.js ubuntu docker containers node-gyp
4个回答
15
投票

如何确保目标主机具有编译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 镜像缓存的使用。最好离开直到事情变得重要为止。


6
投票

如果您需要使用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


3
投票

回顾过去(2年后),管理容器中的节点依赖关系仍然是一个挑战。 我现在做的是:

  1. 构建docker镜像FROM节点:10.16.0-alpine(或其他节点 版本)。 这些是 hub.docker.com 上的官方 node 图像。 码头工人 推荐 alpine,Nodejs 建立在其之上,包括 node-gyp,所以这是一个很好的起点;

  2. 包含 RUN apk add --no-cache 以包含所有库 需要构建依赖模块,例如画布(参见下面的示例);

  3. 在 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]
    ;

1
投票

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"]
© www.soinside.com 2019 - 2024. All rights reserved.