「Ubuntu」のパッケージ管理を学ぼう
はじめに
Linuxにアプリをインストールするには、まずソースコードを取得して、次にconfigureしてmake……というのは過去の話。今どきのディストリビューションのほとんどは何らかのパッケージ管理システムを採用しています。今回はUbuntuにおけるパッケージ管理方法について解説します。
なお、今回からは主にWSL上のUbuntuの機能について解説していきますが、Ubuntuそのものの機能はWSLとそれ以外のプラットフォームとで差異はありません。そのため本連載で解説する内容はWSL以外の環境、例えばベアメタルのUbuntuサーバーや仮想マシン、クラウド、Raspberry PiなどでUbuntuを使う際にも役立ちます。ぜひ参考にしてください。
パッケージとは
ソフトウェアはプログラムのソースコードから作られます。そのため、手元のコンピューター上でソフトウェアを動かすにはソースコードを開発元のリポジトリからチェックアウトし、必要であればパッチを当ててバイナリをビルドし、システムにインストールしなくてはなりません。特定のアプリだけであればともかく、OS全体をこのように手動で構築するのは、非常に困難な作業です。また、世界中のUbuntuユーザーが個別に同じソフトウェアをビルドするのは、エコとは言えません。
そこで、今どきのLinuxディストリビューションの多くは「パッケージ」を使ってソフトウェアを管理しています。パッケージとは、事前にビルドされたソフトウェアのバイナリやライブラリ、画像やドキュメントといったリソース、インストールやアンインストール時に実行すべきスクリプト、パッケージ自身を表すメタデータなどをまとめたアーカイブです。
パッケージはインターネット上にある「リポジトリ」と呼ばれるサーバーに集めて公開されており、ユーザーはここから必要なソフトウェアのパッケージをダウンロードして展開するだけで、そのソフトウェアをインストールできるというわけです。パッケージを使うことで開発元から個別にソースコードを入手したり、調整やビルドといった面倒な作業が不要となるため、システムの運用にかかる手間を大きく削減できます。
Ubuntuのパッケージは、Ubuntuコミュニティにより開発・管理され、Ubuntuのリポジトリサーバー上で公開されています。こうしたパッケージを「公式パッケージ」と呼ぶこともあります。公式パッケージは「UbuntuというOSを構成する一部」と言えるため、安心して利用できます。
これに対して「アプリケーションの開発元」が独自にUbuntu向けとして公開しているパッケージも存在します。こうしたパッケージは「サードパーティパッケージ」として区別されています。サードパーティパッケージの質は玉石混合であり、場合によってはUbuntuのアップグレードに悪影響を与えるような可能性も否定できません。非公式なパッケージを追加する場合は、くれぐれも注意してください。
Ubuntuでは、Debian GNU/Linuxに由来する「Deb」と呼ばれる形式のパッケージを採用しています。
パッケージ管理システムとは
多くのソフトウェアに共通した「ありがちな処理」というものがあります。例えば「JPEG画像を読み込む」「ZIPファイルを展開する」「JSONをパースする」などです。こうした処理を個々のソフトウェアが自前で再実装するのは無駄ですし、バグを作り込む原因にもなります。そこで、こうした処理の多くは別のソフトウェアから再利用しやすいように機能単位で個別に実装されています。これを「ライブラリ」と呼びます。
個々のソフトウェアは、ライブラリの機能を呼び出すことで自前での再実装を防げます。また、特定の機能をライブラリに集約することでメンテナンス性も向上するというわけです。例えばSSL/TLSに脆弱性が見つかったとしても、SSL/TLSを扱うライブラリをアップデートすれば、そのライブラリを利用しているすべてのアプリで脆弱性の対応が完了するというわけです。
こうした事情から、一部のシングルバイナリなソフトウェアを除けば、今どきのソフトウェアが単体で完結していることは稀です。ほとんどのソフトウェアは何らかのライブラリに「依存」しています。そしてLinuxでは、こうしたライブラリの多くをOS全体で共有しており、これを「共有ライブラリ」と呼びます。
こうした事情はパッケージでも同様です。あるアプリのパッケージAが動作するには別のパッケージBが必要で、パッケージBにはまた別のパッケージCが必要で……と、芋づる式に複数のパッケージが必要になることも珍しくありません。GUIの高機能なアプリでは百を越えるパッケージを要求されることもあります。これを「パッケージの依存関係」と呼びます。つまり、あるソフトウェアをインストールしようと思ったら、そのパッケージが要求する依存関係を満たせるよう、必要なすべてのパッケージをダウンロードしてインストールしなくてはならないのです。
パッケージ間の複雑な依存関係をすべて調べ上げ、要求されるすべてのパッケージを手動でインストールするのは、とても現実的ではありません。そこで依存関係を自動的に解決し、必要なすべてのパッケージのダウンロードとインストールを簡単に行えるのが「パッケージ管理システム」です。パッケージ管理システムを利用すれば、インストールされているすべてのパッケージを最新版にアップグレードすることも簡単です。Ubuntuでは「APT」と呼ばれるパッケージ管理システムを用いて、Debパッケージのインストールやアップグレードを行っています。
CLIの基本操作
APTは同名の「apt」コマンドで操作しますが、その前に、UbuntuのCLIにおける基本的な操作方法を覚えておきましょう。まず前回を参考に、Windows TerminalでUbuntu 24.04のプロファイルを開いてください。Ubuntuの標準シェルであるBashが起動し、以下の画面が表示されます。
ウィンドウの左上に「ユーザー名@ホスト名:カレントディレクトリ$
」という文字が表示されています。この文字を「プロンプト」と呼び、シェルがコマンドの入力を受け付けていることを表しています。表示される具体的な文字は環境によって異なりますが、マニュアル等では慣例上、プロンプトを「$
」1文字で表します。そのため、本連載でもコマンドを入力する箇所では、以下のフォーマットで示します。なお、あくまで「$
」はプロンプトを表す記号なので、実際にユーザーが入力するのは「$
」より後の文字列だけです。「$
」ごとコピペしないよう注意してください。
$ 入力するコマンド
本連載におけるコマンド入力の表記方法
プロンプトの右側にカーソルが点滅しています。ここに実行したいコマンドを入力して[Enter]キーで実行します。手はじめに、現在日次を表示する「date」コマンドを実行してみましょう。プロンプトに続いてキーボードから「date」と入力して[Enter]キーを押してください。
$ date
dateコマンドを実行する
現在の日次が表示されました。また、次の行には新しいプロンプトが表示されていることが分かるでしょう。シェルはコマンドの実行が終わると再びプロンプトを表示し、次のコマンドの入力を待機します。
続いて、現在のログイン状況を表示する「w」コマンドを実行してみましょう。
$ w
wコマンドを実行する
現在Ubuntuにログインしているユーザー名や使用している端末、ログイン時刻といった情報が表示されました。このように、プロンプトにコマンドを入力し、コマンドが終了したら次のコマンドを入力し……を繰り返して行くのがCLI操作の基本です。ここではUbuntuのBashの例を紹介しましたが、Windowsのコマンドプロンプト(cmd.exe)やPowerShellも基本的な流れはまったく同じです。
コマンドラインのより詳しい操作方法は、Ubuntuのチュートリアルも参考にしてください。
APTを使いこなす
それでは、実際にaptコマンドを使ってみましょう。
aptのサブコマンド
aptコマンドは、様々なサブコマンドと組み合わせて使います。よく使う代表的なサブコマンドは下表の通りです。
サブコマンド | 用途 |
---|---|
update | パッケージ情報を更新する |
upgrade | インストールされているすべてのパッケージを最新のバージョンに更新する。ただしパッケージの削除が発生する場合は作業を保留する |
full-upgrade | パッケージの削除が発生する場合であっても、すべてのパッケージを最新のバージョンに更新する |
install | 指定したパッケージをインストールする |
remove | 指定したパッケージを削除する |
purge | 指定したパッケージを設定ファイルごと削除する |
autoremove | 依存関係によって自動インストールされたパッケージのうち、現在では不要になったものを削除する |
search | 指定されたキーワードをもとにパッケージを検索する |
list | 指定された条件に一致するパッケージの一覧を表示する |
show | パッケージの詳細な情報を表示する |
例えば、パッケージ情報を更新するには「apt update」、パッケージをインストールするには「apt install」といった具合です。
パッケージ情報の更新
続いて、具体的な実行手順を見ていきましょう。aptコマンドは、ローカルにキャッシュされたパッケージ情報を手がかりに、リポジトリからパッケージ本体のダウンロードやインストールを行う仕組みになっています。そのため、最初にこのキャッシュを最新の状態に更新しなければなりません。キャッシュが古いままだと、リポジトリサーバー上にパッケージの新しいバージョンが存在してもaptコマンドはそれを見つけることができず、インストールやアップグレードが行えなくなってしまうためです。
パッケージ情報のキャッシュを更新するには「apt update」を実行します。
$ sudo apt update
apt updateを実行する
ここで「sudo」という新しいコマンドが登場しました。これは、後に指定したコマンドを別のユーザー権限(通常はrootユーザー)で実行するためのコマンドです。今どきのマルチユーザーのOSでは、一般ユーザーと管理用のスーパーユーザーで権限が分けられているのが一般的です。Windowsでも、システムの設定を変更するときは管理者の権限を要求されますよね。
Linuxもその例に漏れず、システムに対する最高の権限を持つ「root(ルート)」と、一般ユーザーに分けられています*1。WSLディストリビューションのインストール時に作成し、現在Ubuntuにログインしているユーザーは一般ユーザーなのでシステムの変更権限を持ち合わせていません。パッケージ情報の更新はシステムの領域にデータを書き込むため、一般ユーザーでは実行できないのです。
*1: 厳密に言えば、現在のLinuxにおける権限はもっと細分化されており、「なんでもできるrootとそれ以外」という構造ではなくなっています。詳細は省きますので、もし興味があったら「Linuxカーネル ケーパビリティ」などで検索してみてください。
従来のLinuxディストリビューションであれば、こうした作業はrootユーザーで直接ログインして行っていましたが、Ubuntuをはじめとする現代的なディストリビューションではsudoコマンドを使って一時的にrootに「昇格」することで行うのが定石となっています。WSLでUbuntuを起動した直後の画面をよく見てください。英語なので読み飛ばした方もいるかもしれませんが、以下のメッセージが表示されていますよね。
> To run a command as administrator (user "root"), use "sudo <command>". > See "man sudo_root" for details.
(参考訳: コマンドを管理者(rootユーザー)として実行する場合は"sudo コマンド"を使用してください。詳細は"man sudo_root"を参照)
sudoを付けてコマンドを実行するとユーザーのパスワードの入力が求められます。インストール時に設定した自分のパスワードを入力してください。なお、この際にパスワードのエコーバック(「*」などが表示されること)は行われないため、「パスワードが入力できない」と勘違いする人もよくいます。表示されなくてもきちんと入力できているので、気にせずに[Enter]キーを押してください。
これで、正しくパッケージ情報が更新されました。
パッケージの検索
aptコマンドでパッケージをインストールするためには、対象のパッケージ名を知っておく必要があります。そこで、キーワードをもとにパッケージを検索するのが「apt search」です。このサブコマンドはシステムへの変更等を行わないため、sudoなしで実行できます。例として、引数に「docker」を指定してDockerに関するパッケージを探してみましょう。なお、引数には文字列だけでなく、POSIX正規表現が使用できます。
$ apt search docker
dockerというキーワードでパッケージを検索する
コマンドを実行すると、指定したキーワードを含むパッケージが一覧表示されます。緑色で表示されているのがパッケージ名で、その横にインストール元のリポジトリ、パッケージのバージョン、パッケージのアーキテクチャが表示されています。その下にはパッケージの簡単な説明が表示されます。これを手がかりに、パッケージを探してみましょう。
ただし、searchサブコマンドはパッケージリストに対して全文検索を行うため、これだけだと膨大なパッケージがヒットしてしまいます。そこで「-n」オプションを付けると検索対象を「パッケージ名のみ」に絞ることができます。やってみましょう。
$ apt search -n docker
名前に「docker」を含むパッケージを検索する
だいぶ絞り込めたのではないでしょうか。そして、パッケージの説明を見ると、UbuntuにおけるDockerランタイムのパッケージは「docker.io」パッケージだろうと、アタリをつけることができるわけです。
パッケージの詳細
searchサブコマンドでは、各パッケージの概要レベルの説明しか表示されませんでした。パッケージのより詳細な情報は「apt show」で確認できます。引数にパッケージ名を指定してください。またこのサブコマンドも情報を参照するだけなのでsudoは不要です。
$ apt show docker.io
docker.ioパッケージの詳細を確認する
パッケージ名やバージョンだけでなく、依存しているパッケージ、同時にインストールすることが推奨されているパッケージ、開発元のWebページ、パッケージの詳細な説明などが表示されました。Descriptionに書かれている内容やHomepageがMoby ProjectのURLであることから、このパッケージはDockerのランタイムであるということが分かります。
パッケージのインストール
パッケージをインストールするには「install」サブコマンドにパッケージ名を指定します。例えば、Dockerをインストールするには、先ほど特定した「docker.io」パッケージを指定します。なお、パッケージのインストールにはroot権限が必要となるためsudoを付けて実行します。
$ sudo apt install docker.io
docker.ioパッケージをインストールする
本当にパッケージをインストールして良いか「y/n」の確認プロンプトが表示されます。キーボードから[y]キー→[Enter]キーを押してください。
なお、都度確認を求められるのが面倒な場合は「apt install」に「-y」オプションを指定して実行してください。常に[y]キーを押したものとして確認をスキップできます。
$ sudo apt install -y docker.io
「y/n」の確認を省略する例
パッケージのアンインストール
インストール済みのパッケージをアンインストールするには「remove」サブコマンドにパッケージ名を指定します。こちらもroot権限が必要なのでsudoを付けて実行してください。ただし、不用意にパッケージをアンインストールするとシステムに問題が発生する可能性も否定できません。アンインストールするのは自分がインストールしたパッケージや、確実に不要と分かっているパッケージに限定するのが無難でしょう。
$ sudo apt remove docker.io
docker.ioパッケージをアンインストールする
アンインストール時も本当に実行して良いかの確認プロンプトが表示されます。「-y」オプションで確認をスキップできるのも同様です。
なお、removeサブコマンドでは設定ファイルは削除されないため、パッケージをインストールし直せばアンインストール前の状態に戻すことができます。設定ファイルまで綺麗に削除したい場合は、代わりに「purge」サブコマンドを使用してください。
パッケージのアップグレード
「upgrade」サブコマンドを使うと、インストール済みのすべてのパッケージを最新のバージョンへとアップグレードできます。すべてのパッケージが対象となるため、パッケージ名を指定する必要はありません。
$ sudo apt upgrade
パッケージを最新のバージョンにアップグレードする
アップグレード可能なパッケージが存在する場合はその一覧が表示され、インストール時と同様の確認プロンプトが表示されます。アップグレードを続行して良ければ[y]キー→[Enter]キーを押してください。また「-y」オプションも同様に利用できます。「apt upgrade」を行うだけでUbuntuを最新の状態に保つことができるので、定期的に実行するようにしましょう。
ごく稀に、パッケージの依存関係が変更になった等の理由でアップグレード時に既存パッケージが削除されることがあります。upgradeサブコマンドは、パッケージの削除が伴う場合にそのパッケージのアップグレードを行わず、作業を保留します。その結果として一部のパッケージが古いままになる可能性があるため、「パッケージを削除しても構わないので、とにかくすべてを最新にしたい」という場合は、代わりに「full-upgrade」サブコマンドを使用してください。
$ sudo apt full-upgrade
パッケージの削除が発生する場合でも、すべてのパッケージをアップグレードする
パッケージの一覧表示
「list」サブコマンドを使うと、条件を満たすパッケージの一覧を表示できます。以下のように「--installed」オプションを付けると現在システムにイスントール済みのパッケージ一覧を確認できます。
$ apt list --installed
インストール済みのパッケージ一覧を表示する
また「--upgradable」オプションを付けて実行すると、インストール済みのパッケージのうちアップグレード可能なものの一覧を表示できます。
$ apt list --upgradable
より新しいバージョンが存在するパッケージ一覧を表示する
Ubuntuを使っていくと「このパッケージ、インストールされていたっけ?」となるシーンがよくあります。そのようなときは「apt list」で確認してみましょう。
パッケージの内容の確認
Debパッケージを操作する「dpkg」コマンドを使えば、個々のパッケージをより詳細に管理できます。冒頭で「パッケージには実行バイナリやドキュメント、画像等のリソースが含まれている」と説明しました。それでは、あるパッケージ内にはどのようなファイルが含まれているのでしょうか。これを調べたいときは「-L」オプションを付けてdpkgコマンドを実行します。引数にはインストール済みの調査したいパッケージ名を指定してください。以下のコマンドでは、Linuxで使われる基本的なコマンド群を提供しているGNU Coreutilsのパッケージの内容を調べることができます。
$ dpkg -L coreutils
coreutilsパッケージに含まれるファイル一覧を表示する
逆に、システム上にインストールされたあるファイルが、どのパッケージに所属しているかを知りたいこともあるでしょう。こういうときは「-S」オプションを付けてdpkgコマンドを実行します。引数には調べたいファイルをフルパスで指定してください。以下のコマンドでは、ファイルの結合や表示に使う「cat」コマンドが、どのパッケージからインストールされているかを調べます。
$ dpkg -S /usr/bin/cat
catコマンド(/usr/bin/cat)が含まれているパッケージを調べる
「apt」と「apt-get」の関係
以前から、Ubuntuやその派生元であるDebian GNU/Linuxを使っている人であれば「apt-get」や「apt-cache」というコマンドをご存知かもしれません。実は、以前のUbuntuではパッケージのインストールやアップグレード(installやupgradeサブコマンドなど)は「apt-get」、パッケージ情報の検索(searchサブコマンドなど)は「apt-cache」と2つのコマンドを使い分けていました。「これは面倒だ」ということで、この2つのコマンドを統合したのが「apt」です。そのため、現在ではとりあえずaptコマンドだけを使っていれば問題ありません。
ただし、すべてのケースでaptコマンドを使うべきかといえば、そうでもありません。aptコマンドは人間が対話的に使用することを前提としており、コマンド出力が今後変更される可能性もあるため、シェルスクリプトやDockerfileなどで使用する場合は現在でもapt-getが推奨されています。
また、aptとapt-getではupgradeサブコマンドの挙動に違いがあります。先ほど「aptではパッケージの削除が伴うアップグレードは保留される」と説明しました。apt-getでは、これに加えてパッケージの追加を伴うアップグレードも保留されます。Ubuntuにおいて、アップグレード時に別のパッケージが追加される代表格がカーネルパッケージです。実は「apt-get upgrade」ではOSのカーネルがアップグレードされないのです。apt-getでカーネルをアップグレードするには「dist-upgrade」サブコマンドを使う必要があります。これはaptの「full-upgrade」に相当するサブコマンドですが、名前が異なります。こうした違いにも注意してください。
「apt update」を省略するには
aptはパッケージのインストールやアップグレードといった操作をする前にapt updateでパッケージ情報を更新しておく必要があります。そのため、実行するコマンドがupdateとinstall/upgradeの2本立てになってしまうことを面倒に思うかもしれません。特に、Dockerのイメージビルドでは実行したコマンドごとにイメージレイヤーが作られてしまうため、以下のように2つのコマンドを連結している人も多いのではないでしょうか*2。
*2: 前述の通り、Dockerfileなどの内部ではaptではなくapt-getの使用が推奨されているため、この例でもそのように記述しています。RUN apt-get update && apt-get install -y (パッケージ名)Dockerfileにおけるaptの典型的な例
実は、Ubuntu 24.04のaptには*3「-U」というオプションが追加されています。例えば、以下のようにコマンドを実行すると「install」の実行前に、自動的に「update」を行います。
*3: 厳密にはapt 2.7.0以降で利用できるオプションです。$ sudo apt install -U (パッケージ名)
apt updateを省略できるため、場合によっては便利かもしれません。活用してみてください。
おわり
今回はUbuntuを使う上で必須となる、パッケージの管理について解説しました。Ubuntuには数万を越すパッケージが用意されているので、メジャーなツールであれば、その多くを簡単にインストールできるでしょう。例えば、WebサーバーのApacheやNginx、データベースのMySQLやPostgreSQLなど、いずれもAPTを使ってインストールできます。またAPTでパッケージをインストールしておけば、Ubuntuが提供するセキュリティアップデートの恩恵にも与れます。
そんな便利なAPTですが、OSがパッケージを提供しているため「バージョンがOSのライフサイクルに縛られてしまう」という問題もあります。そこで次回は、この問題を解決する「ユニバーサルパッケージ」について解説します。