Создание пакетов в разных форматах с помощью fpm

Разница в форматах, используемых различными дистрибутивами Linux, может стать проблемой для разработчиков программного обеспечения, желающих выпускать дружественные проекты, которые легко установить. Debian и Ubuntu используют пакеты .deb, а Fedora и RedHat – пакеты .rpm. Они несовместимы, а инструменты, необходимые для их создания, могут оказаться довольно трудными для тех, кто не знаком с особенностями каждого из них.

Разработчики проделывают тяжелую работу для поддержки пакетов, включенных в официальные репозитории, но в некоторых ситуациях у вас может появиться необходимость выпускать программное обеспечение для этих дистрибутивов на своем сайте или создать пакеты для своей организации. Это традиционно связано с изучением работы по меньшей мере нескольких инструментов для каждого из упаковочных семейств.

Чтобы свести к минимуму сложности этого процесса, был создан инструмент fpm. С помощью fpm вы можете легко создавать файлы .deb и .rpm, не зная ни одной из команд упаковки. В этом мануале мы обсудим, как использовать fpm для создания пакетов разных форматов в Ubuntu 14.04.

Установка fpm

Основной метод распространения инструмента fpm — это Ruby gem. Чтобы подготовить систему к установке fpm, установите пакеты разработки Ruby и инструменты для создания программного обеспечения, необходимые для компиляции дополнительного программного обеспечения.

Обновите индекс пакетов и установите все необходимое:

sudo apt-get update
sudo apt-get install ruby-dev build-essential

После этого можно установить fpm:

sudo gem install fpm

Это установит fpm на системном уровне и сделает его доступным для любого пользователя в системе. Традиционно создавать пакеты рекомендуется как обычный пользователь без полномочий root. Это безопаснее – возникновение ошибки упаковки в root может повлиять на всю систему.

Теперь у вас есть исполняемый файл fpm. Вы можете проверить это, запросив справочную информацию инструмента:

fpm --help
Intro:
This is fpm version 1.2.0
If you think something is wrong, it's probably a bug! :)
Please file these here: https://github.com/jordansissel/fpm/issues
You can find support on irc (#fpm on freenode irc) or via email with
fpm-users@googlegroups.com
Usage:
fpm [OPTIONS] [ARGS] ...
. . .

Теперь можно приступать к сборке пакетов.

Базовые функции fpm

Инструмент fpm может сам сообщить вам, что ему нужно для завершения сборки пакета. Чтобы получить представление об основных требованиях, вы можете вызвать команду без аргументов:

fpm
Missing required -s flag. What package source did you want? {:level=>:warn}
Missing required -t flag. What package output did you want? {:level=>:warn}
No parameters given. You need to pass additional command arguments so that I know what you want to build packages from. For example, for '-s dir' you would pass a list of files and directories. For '-s gem' you would pass a one or more gems to package from. As a full example, this will make an rpm of the 'json' rubygem: `fpm -s gem -t rpm json` {:level=>:warn}
Fix the above problems, and you'll be rolling packages in no time! {:level=>:fatal}

Этот вывод перечисляет основные элементы, которые нужно предоставить для создания пакета. Типичный вызов команды выглядит следующим образом:

fpm -s тип_источника -t целевой_тип имя_или_расположение_источника

Источник может быть нескольких типов. Тип источника также определяет способ передачи имени или расположения источника в команду. В следующем разделе мы обсудим возможные форматы ввода и вывода.

Некоторые форматы требуют дополнительных утилит, которые будут установлены для преобразования в отдельные типы пакетов. Поскольку вы уже установили необходимые компоненты Ruby для того, чтобы fpm работал в Ubuntu, вы можете попробовать выполнить преобразование gem-а Ruby в пакет .deb.

Давайте выберем популярный gem, например bundler. Чтобы создать пакет .deb из пакета bundler, расположенного на rubygems.org, нужно ввести:

fpm -s gem -t deb bundler
Created package {:path=>"rubygem-bundler_1.6.5_all.deb"}

В локальном каталоге появится файл rubygem-bundler_1.6.5_all.deb (ваш номер версии может отличаться). Теперь можно установить его, как и любой другой пакет .deb:

sudo dpkg -i rubygem-bundler_1.6.5_all.deb

Когда вы проверите список установленных gem-ов, вы увидите, что теперь у вас есть пакет:

gem list
*** LOCAL GEMS ***
arr-pm (0.0.9)
backports (3.6.0)
bundler (1.6.5)
cabin (0.6.1)
childprocess (0.5.3)
clamp (0.6.3)
ffi (1.9.3)
fpm (1.2.0)
json (1.8.1)

Вы могли бы так же легко использовать другой исходный или выходной формат, но для этого системе требуются некоторые дополнительные инструменты для преобразования форматов. Мы обсудим это позже.

Исходные и целевые форматы

Инструмент fpm может работать с несколькими различными исходными и целевыми форматами. Каждый из них имеет свои собственные требования и функции.

В случае если у формата существует относительно стандартный пакетный индекс онлайн (например, rubygems.org для файлов Ruby gem), fpm может автоматически находить индекс и загружать необходимые файлы. Сначала он будет искать совпадение в текущем каталоге, а затем в индексе, если локально совпадений не найдено.

В настоящее время поддерживаются следующие типы источников:

Тип Описание Передача имени или расположения источника Дополнительные пакеты
dir Каталоги или файлы Передайте абсолютный или относительный путь файлов проекта в локальной файловой системе. (не требуются)
tar Tarball архивы Передайте путь к расположению tarball (сжатого или несжатого) в локальной файловой системе. (не требуются)
gem Ruby gem-ы Передайте название gem-аRuby, которое можно найти на www.rubygems.org. Он будет автоматически загружен для создания пакета. ruby, rubygems-integration
python Пакеты Python Передайте имя пакета Python так, как вы передавали бы его в easy_install. Поиск по именам выполняется в Python Package Index, найденные автоматически загружаются для создания пакета. python-setuptools
pear Расширения PHP Передайте имя расширения или приложения PHP, найденного на pear.php.net. Соответствующие файлы будут автоматически загружаться при создании пакета. php-pear
cpan Модули Perl Передайте имя модуля Perl, как на cpan.org. Файлы будут автоматически загружены и использованы для сборки пакета. cpanminus
zip Архивированная структура каталога Передайте расположение zip-файла в локальной файловой системе. zip
npm Модули Node.js Передайте имя модуля Node.js, как указано на npmjs.org. Пакет будет автоматически загружен и использован для создания выходного пакета. npm
osxpkg Пакет OS X Передайте расположение в локальной файловой системе пакета OS X (будет работать только с pkgbuild в пути). pkgbuild (доступно только для систем OS X)
empty (нет) Используется для создания пакета без каких-либо реальных пакетов – чаще всего для метапакетов, которые содержат только зависимости. (не требуются)
deb Пакеты .deb Передайте расположение файла .deb в локальной файловой системе. (не требуются в Debian-подобных системах)
rpm Пакеты .rpm Передайте расположение файла .rpm в локальной файловой системе. rpm

Существует также несколько вариантов целевых форматов упаковки. В приведенной ниже таблице описаны некоторые из них:

Выходной пакет Описание Дополнительные пакеты
deb Пакет в стиле Debian, который можно установить в системах Debian или Ubuntu. (не требуются в Debian-подобных системах)
rpm Пакет RedHat, который можно установить в системах CentOS, Fedora или RedHat. rpm
zip Zip-файл, содержащий каталоги и файловую структуру входного пакета. zip
tar Tarball (сжатый или несжатый) структуры каталогов входного пакета. (не требуются)
dir Каталог для извлечения входного пакета. (не требуются)
sh Самораспаковывающийся файл .sh. Это скрипт оболочки с файлом tar, который будет извлечен при запуске. (не требуются)
osxpkg Пакет для OS X. Для создания этих пакетов нужно работать в OS X с установленным пакетом pkgbuild. pkgbuild (доступно только для систем OS X)
solaris Пакет, подходящий для установки в системе Solaris. У вас должны быть установлены pkgproto и pkgmk, которые доступны только на компьютерах Solaris. pkgproto, pkgmk(доступно только для систем Solaris)
pkgin Пакет, подходящий для установки на BSD-системах. У вас должен быть установлен пакет pkg_create, который доступен только в системах BSD. pkg_create (доступно только для систем BSD)
puppet Модуль Puppet, который можно использовать для установки в различных системах. (Примечание: этот формат работает некорректно с текущей версией fpm). (нельзя протестировать в нерабочем состоянии)

Как видите, некоторые форматы как исходных, так и целевых спецификаций требуют, чтобы вы работали в определенной операционной системе. Поскольку мы демонстрируем этот инструмент на Ubuntu 14.04, исходный формат osxpkg и выходные форматы osxpkg, solaris и pkgin будут недоступны.

Опции fpm

Используя информацию из таблиц в приведенном выше разделе, вы можете создавать базовые пакеты с настройками fpm по умолчанию. Однако в большинстве случаев вам нужно предоставить дополнительную информацию, чтобы сформировать требуемый пакет.

Опции fpm указываются перед аргументами источников, которые определяют расположение или имя исходного пакета.

Существует много разных опций для fpm. Ниже мы рассмотрим только некоторые из наиболее распространенных опций. Получить полный список опций позволяеткоманда fpm —help.

  • -C: каталог, в который нужно перейти до поиска файлов.
  • —prefix: путь к каталогу, в котором будут установлены файлы в выходном пакете.
  • -p: имя и путь пакета. Это может переопределить имя результирующего файла.
  • -n: имя, которое вы хотите использовать для пакета. Это имя отображается в инструментах упаковки платформы.
  • -v: номер версии, которую вы хотите использовать для своего пакета.
  • —iteration: информация о релизе пакета. Имя дистрибутива для этого номера может отличаться; обычно это способ отслеживать версию пакета, в отличие от версии приложения.
  • —license: лицензионное имя пакета. Включает тип лицензии в метаданных, но не содержит связанный файл лицензии в самом пакете.
  • —category: категория, к которой относится этот пакет (можно использовать для организации пакета в репозитории).
  • -d: зависимости пакета (можно использовать несколько раз).
  • —provides: можно использовать для указания функциональности системы, предоставляемой этим пакетом.
  • —conflicts: определяет пакеты, которые несовместимы с вашим пакетом.
  • —replaces: используетсядля указания пакетов, которые необходимо удалить при установке этого пакета.
  • —config-files: используется для маркировки конфигурационных файлов в пакете. Как правило, менеджеры пакетов оставят такие файлы при удалении пакета.
  • —directories: помечает каталог как принадлежащий пакету.
  • -a: указывает архитектуру пакета.
  • -m: позволяет переопределить поле сопровождающей стороны пакета. По умолчанию здесь будет использоваться username@host.
  • -e: вручную просмотреть и отредактировать файл спецификации до создания пакета. Эту опцию можно использовать для корректировки любых значений по умолчанию, которые были использованы в спецификации.
  • —description: описание пакета.
  • —after-install, —before-install, —after-remove, —before-remove: файлы сценариев, которые должны запускаться в соответствующее время.

Существует также несколько специфичных опций для разных форматов. Для получения полного списка используйте подкоманду help.

Кастомизация пакетов

Если вы не хотите просто перевести пакет из одного формата в другой, вам нужно использовать другой рабочий процесс.

Этот процесс будет отражать традиционную упаковку, но также обеспечит возможность быстрого создания нескольких выходных форматов. Общий рабочий процесс  показан ниже (предполагается, что рассматриваемое приложение использует стандартные процессы компиляции и установки ./configure, make, make install).

Для начала установите все необходимые зависимости. Затем получите исходный пакет проекта со своего веб-сайта и поместите его в рабочий каталог:

mkdir ~/build
cd ~/build
wget http://example.com/project.tar.gz

Теперь вы можете извлечь файл и перейти в полученный каталог:

tar xzvf project.tar.gz
cd project

В этом каталоге у вас будут исходные файлы приложения, которое нужно упаковать. Теперь у вас есть возможность внести некоторые изменения в файлы и отладить параметры.

Обычно для указания параметров во время сборки используется сценарий ./configure. Ознакомьтесь с документацией проекта, чтобы узнать, какие опции компиляции доступны. Вы можете указать их, вызвав скрипт configure с этими опциями:

./configure --compilation_option=value --another_option=value --optional_flag ...

Это создаст или изменит файлы, которые считываются командой make при создании пакета. Теперь можно создать файлы установки, набрав:

make

Вместо того чтобы устанавливать кастомизированные файлы в своей системе, попробуйте установить их в пустой фиктивный каталог, из которого можно будет собрать реальный пакет. Создайте каталог для установки пакета:

mkdir -p /tmp/project

Можно пометить этот новый каталог как корневое расположение установки, передав параметр DESTDIR:

make DESTDIR=/tmp/project install

Теперь пакет полностью установлен в пустой каталог. Команда создала всю необходимую структуру каталогов, но в этом каталоге нет ничего несвязанного с пакетом.

Это ваша вторая возможность кастомизировать свою настройку. Если вы хотите включить в иерархию дополнительные файлы для установки, вы можете добавить их в соответствующее место в этой структуре.

Когда все будет готово, вы можете использовать fpm для создания соответствующего пакета. Например, команде fpm можно передать некоторую информацию о версии и описание пакета. Также можно перечислить информацию о зависимостях или предоставить дополнительные сведения, которые повлияют на создание метафайлов упаковки.

Можно использовать структуру каталогов для создания нескольких форматов упаковки. Например, чтобы затем создать пакет .deb, введите:

fpm -s dir -t deb -C /tmp/project --name project_name --version 1.0.0 --iteration 1 --depends debian_dependency1 --description "A sample package" .

Это создаст пакет под названием project-name_1.0.0-1_amd64.deb в текущем каталоге.

Затем вы можете изменить несколько параметров для создания пакета .rpm (при условии, что вы установили rpm):

fpm -s dir -t rpm -C /tmp/project --name project_name --version 1.0.0 --iteration 1 --depends  redhat_dependency1 --description "A sample package" .

Это создаст пакет project_name-1.0.0-1.x86_64.rpm в текущем каталоге.

Как видите, fpm позволяет довольно легко создать индивидуальные пакеты. Инструмент берет на себя большинство трудных задач пакетирования.

Заключение

Использование fpm может облегчить вашу работу по подготовке пакетов для вашей инфраструктуры или распространение общедоступных загружаемых пакетов проекта. Хотя это и не идеальное решение пакетирования для репозиториев реальных дистрибутивов (из-за проблем с политикой), преимущества fpm можно использовать во многих ситуациях.

Tags: ,