【问题标题】:need a little help to create an rpm package for a nodejs app需要一点帮助来为 nodejs 应用程序创建一个 rpm 包
【发布时间】:2023-06-11 04:37:01
【问题描述】:

我已经按照this 的说明准备了一个构建框,我四处搜索并做了一个 hello world rpm 构建,但仍然不确定打包一堆 js 文件的最佳方法是什么(nodejs 应用程序) .我想:

  1. 将文件部署到某个位置
  2. 运行#npm install
  3. 运行命令启动节点监听器/守护进程。

我做了一个非常简单的规范文件,如下所示:

Name:           nodejsapp
Version:        1.0
Release:        0
Summary:        API for a Platform

Group:          Group
License:        License
URL:            somewebsite
Distribution:   Linux CentOS
Source0:        %{name}-%{version}.tar.gz

%description
CDR Platform is awesome product.


%prep

%install
install -m 755 -d $RPM_BUILD_ROOT/opt/cdr/api

%clean
rm -rf $RPM_BUILD_ROOT


%files
%defattr(-,root,root,-)

上述构建,但我安装时没有任何反应!我不确定我是否完全了解 rpmbuild 的运作方式。

那么在这种情况下我需要使用哪个宏? 我需要在 %files 下创建文件列表吗? 在运行 rpmbuild 之前我需要 gzip 文件吗?或者我可以在 rpmbuild 期间压缩它们吗?

感谢任何帮助。

【问题讨论】:

  • 你不应该让你的 rpm 启动任何服务。它可以将它们设置为通过任何应该启动它的机制来启动,但通常不应该启动服务本身。
  • @EtanReisner 谢谢你,是的,我也读过这个文件,刚接触这个文件我不知道从哪里开始?由于我不编译代码,我是否需要 %build %install .. 等与构建代码相关的那些?
  • 您不需要所有这些部分。事实上,从技术上讲,您不需要 任何 它们。在实践中,您至少希望 %prep 提取您的源/等。和%install 将文件复制到构建根目录。然后%files 列出要包含在 rpm 中的文件(在 buildroot 下)。
  • @EtanReisner 你是说我需要列出包中包含的每个文件吗?他们太多了!
  • @EtanReisner 所以我应该编写一个 shell 命令来复制 %files 部分中列出的文件?我不确定这是否有意义?那我为什么要列出它们呢?

标签: linux node.js rpm centos6 rpmbuild


【解决方案1】:

可以在here 找到为 Fedora EPEL 存储库打包 nodejs 应用程序的指南。在打包您自己的 nodejs 应用程序时,它们是一个很好的参考。

您没有提及您使用的是哪个版本或哪个发行版,但我假设它是最近的发行版,因此您要启动的服务将在 systemd 下运行。 Fedora systemd 打包指南可以在here找到。

我还假设你使用 github 来管理代码,它是一个纯 JS 应用程序。

对于没有依赖关系或仅依赖于已打包在 EPEL 中的 nodejs 模块的 nodejs 模块/应用程序,以下 SPEC 文件(另存为 SPECS/nodejs-myapp.spec)将起作用。

%define debug_package %{nil}
#
# automatically generate requires and provides from package.json
#
%{?nodejs_find_provides_and_requires}

#
# filter out any false provides created due to dependencies with native components
#
%{?nodejs_default_filter}

#
# name of zip file containing source without .zip extension
#
%define modname myapp

Summary: A nodejs app with a systemd daemon
Name:    nodejs-%{modname}
Group:   Applications/Tools
Version: 0.1
Release: 1
License: Unlicense
URL:     https://github.com/myuser/myapp
Source0: %{modname}-%{version}.zip
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildArch: noarch
ExclusiveArch: %{nodejs_arches} noarch
BuildRequires: nodejs-packaging
BuildRequires: systemd

%description
A nodejs app that installs as a systemd service

%prep
%setup -q -n %{modname}-%{version}

%build

%{__rm} -f .gitignore
#
# Fedora guidlines do not allow bundled modules
# use nodejs_symlink_deps in the install section to generate
# links based on package.json contents
#
%{__rm} -rf node_modules

%install
rm -rf $RPM_BUILD_ROOT

#
# copy in the module source
#
%{__install} -d  $RPM_BUILD_ROOT%{nodejs_sitelib}
%{__cp} -r $RPM_BUILD_DIR/%{modname}-%{version} $RPM_BUILD_ROOT%{nodejs_sitelib}/%{modname}
#
# link the daemon binaries into sbindir
#
%{__install} -d  $RPM_BUILD_ROOT%{_sbindir}
%{__ln_s} %{nodejs_sitelib}/%{modname}/bin/myappd $RPM_BUILD_ROOT%{_sbindir}/myappd

#
# link in any dependent nodejs modules referenced in package.json
#
%nodejs_symlink_deps

#
# documents will be handled by %doc, so remove them from buildroot
#
%{__rm} -rf $RPM_BUILD_ROOT%{nodejs_sitelib}/%{modname}{CHANGELOG.md,LICENSE.md,README.md,docs}

#
# Create a systemd unit file
#
cat << __EOF > $RPM_BUILD_ROOT%{_unitdir}/myappd.service
[Unit]
Description=MyApp provides the best API
Documentation=man:myapp.service(8)

[Service]
Type=simple
ExecStart=/usr/sbin/myappd

[Install]
WantedBy=multi-user.target
__EOF

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root)
%doc CHANGELOG.md LICENSE.md README.md docs
%{nodejs_sitelib}/%{modname}
%{_sbindir}/myappd
%{_unitdir}/myappd.service

%changelog
* Sun Mar 22 2015 BitByteDog
- Initial spec file for myapp

此规范文件还将处理具有已打包为 EPEL 一部分的依赖项的 nodejs 模块。 RPM 的 auto requires/provides 功能使用模块中的 package.json 文件在最终的 RPM 包中创建必要的 requires 依赖项。

应使用以下命令从 github 将源 zip 下载到 SOURCES 目录中:

wget -O SOURCES/myapp-0.1.zip https://github.com/myuser/myapp/archive/v0.1.zip

RPM 是使用以下命令构建的:

rpmbuild -ba SPECS/nodejs-myapp.spec

创建的 systemd 单元文件非常简单,请阅读提供的链接以及相关的 systemd 文档以根据您的要求进行定制。您需要使用以下命令启用和启动服务:

systemctl enable myappd.service
systemctl start myappd.service

之后会自动启动。

如果您想在您的 JS 应用程序中包含捆绑模块,可以使用 npm 完成。 首先添加标签:

BuildRequires: npm
AutoReq: no
AutoProv: no

抑制自动需要/提供生成。然后删除该行

%{__rm} -rf node_modules

来自 %build 部分。也换行

%nodejs_symlink_deps

在 %install 中的行

#
# npm will bundle in all dependent modules from the npm registry
# (bundling is OK for private packages but not for EPEL packages)
#
npm -g -q --production --prefix="${RPM_BUILD_ROOT}%{_prefix}" install

应用中捆绑的所有模块和 package.json 中列出的所有依赖项都将捆绑到您的应用中,使其成为独立应用。

上述命令中npm的用法说明

  • npm install 在包/应用程序目录中执行,并在该目录中包含的包上运行。
  • -g 将包作为全局包安装在当前工作目录中
  • -q 仅打印警告和错误
  • --production 不要复制 devDependencies
  • --prefix= 安装在前缀目录中

效果是将本地目录下的nodejs应用复制到${RPM_BUILD_ROOT}%{_prefix}准备打包。

【讨论】:

  • 是否需要在 user/bin 目录下安装 nodejs 应用?或者这只是一个最佳实践?我将它安装在 /opt/myapp
  • /opt/myapp 是放置 nodejs 的好(且正确)的地方。原因是有一个 EPEL 包 nodejs 安装到 /usr 中。将 nodejs 安装在顶部或代替 EPEL 包可能会导致冲突或产生意外的副作用,因为安装的所有 EPEL nodejs 应用程序现在都将使用您的 node 版本。
  • 感谢@BitByteDog 我注意到这是在讨论打包一个节点扩展,该扩展将在 npm 注册表中可用,而我正在做的工作是一个非公共应用程序的 api。我不确定这些准则是否适用?当我可以部署到文件系统然后运行我的守护进程(我永远使用)时,我真的想让它变得那么复杂(链接节点模块、自动提供、过滤掉自动提供......等)。您对此有何看法?
  • rpmbuild 是打包项目的绝佳工具——我将它用于 JS、C、C++、Java 项目,因为 RPMS 易于处理且功能强大。如果您不希望 RPM 生成自动提供/要求,请使用“AutoReq: no”和“AutoProv: no”标签。 NPM 仅用于将文件从当前目录复制到 PREFIX 目录 - 可以使用 cp 完成。我使用“npm”是因为它了解 nodejs 程序和模块的结构。使用 cp 您必须在 PREFIX 目录中手动创建目标文件结构。我已经在答案中扩展了 NPM 的使用。
  • 如果您的应用程序依赖于操作系统,或者您需要运行安装/删除脚本,那么 RPM 是个好主意。我假设您使用的是 NPM,因为大多数应用程序使用一两个模块,并且 NPM 可以很好地管理 nodejs 依赖项。如果您正在编写一个没有依赖项的简单应用程序,则只需将其复制到 /opt/myapp/bin/myapp 和 chmod a+x /opt/myapp/bin/myapp。
最近更新 更多