「Ubuntu」のパッケージ管理を学ぼう

2024年12月4日(水)
水野 源
第3回の今回は、WSL上の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が起動し、以下の画面が表示されます。

Windows TerminalでUbuntu 24.04を起動した状態

ウィンドウの左上に「ユーザー名@ホスト名:カレントディレクトリ$」という文字が表示されています。この文字を「プロンプト」と呼び、シェルがコマンドの入力を受け付けていることを表しています。表示される具体的な文字は環境によって異なりますが、マニュアル等では慣例上、プロンプトを「$」1文字で表します。そのため、本連載でもコマンドを入力する箇所では、以下のフォーマットで示します。なお、あくまで「$」はプロンプトを表す記号なので、実際にユーザーが入力するのは「$」より後の文字列だけです。「$」ごとコピペしないよう注意してください。

$ 入力するコマンド

本連載におけるコマンド入力の表記方法

プロンプトの右側にカーソルが点滅しています。ここに実行したいコマンドを入力して[Enter]キーで実行します。手はじめに、現在日次を表示する「date」コマンドを実行してみましょう。プロンプトに続いてキーボードから「date」と入力して[Enter]キーを押してください。

$ date

dateコマンドを実行する

dateコマンドを実行した例

現在の日次が表示されました。また、次の行には新しいプロンプトが表示されていることが分かるでしょう。シェルはコマンドの実行が終わると再びプロンプトを表示し、次のコマンドの入力を待機します。

続いて、現在のログイン状況を表示する「w」コマンドを実行してみましょう。

$ 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でも、システムの設定を変更するときは管理者の権限を要求されますよね。

WSLのインストール時に表示された確認ダイアログの例

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]キーを押してください。

sudoを付けてコマンドを実行するとパスワードを求められる。正しく入力するとrootに昇格してコマンドを実行できる

これで、正しくパッケージ情報が更新されました。

apt updateが実行できた状態。画面にエラーなどが表示されていないか確認しておこう

パッケージの検索

aptコマンドでパッケージをインストールするためには、対象のパッケージ名を知っておく必要があります。そこで、キーワードをもとにパッケージを検索するのが「apt search」です。このサブコマンドはシステムへの変更等を行わないため、sudoなしで実行できます。例として、引数に「docker」を指定してDockerに関するパッケージを探してみましょう。なお、引数には文字列だけでなく、POSIX正規表現が使用できます。

$ apt search docker

dockerというキーワードでパッケージを検索する

コマンドを実行すると、指定したキーワードを含むパッケージが一覧表示されます。緑色で表示されているのがパッケージ名で、その横にインストール元のリポジトリ、パッケージのバージョン、パッケージのアーキテクチャが表示されています。その下にはパッケージの簡単な説明が表示されます。これを手がかりに、パッケージを探してみましょう。

apt searchの実行例

ただし、searchサブコマンドはパッケージリストに対して全文検索を行うため、これだけだと膨大なパッケージがヒットしてしまいます。そこで「-n」オプションを付けると検索対象を「パッケージ名のみ」に絞ることができます。やってみましょう。

$ apt search -n docker

名前に「docker」を含むパッケージを検索する

パッケージ名で検索した例

だいぶ絞り込めたのではないでしょうか。そして、パッケージの説明を見ると、UbuntuにおけるDockerランタイムのパッケージは「docker.io」パッケージだろうと、アタリをつけることができるわけです。

パッケージの詳細

searchサブコマンドでは、各パッケージの概要レベルの説明しか表示されませんでした。パッケージのより詳細な情報は「apt show」で確認できます。引数にパッケージ名を指定してください。またこのサブコマンドも情報を参照するだけなのでsudoは不要です。

$ apt show docker.io

docker.ioパッケージの詳細を確認する

apt showの実行例

パッケージ名やバージョンだけでなく、依存しているパッケージ、同時にインストールすることが推奨されているパッケージ、開発元のWebページ、パッケージの詳細な説明などが表示されました。Descriptionに書かれている内容やHomepageがMoby ProjectのURLであることから、このパッケージはDockerのランタイムであるということが分かります。

パッケージのインストール

パッケージをインストールするには「install」サブコマンドにパッケージ名を指定します。例えば、Dockerをインストールするには、先ほど特定した「docker.io」パッケージを指定します。なお、パッケージのインストールにはroot権限が必要となるためsudoを付けて実行します。

$ sudo apt install docker.io

docker.ioパッケージをインストールする

本当にパッケージをインストールして良いか「y/n」の確認プロンプトが表示されます。キーボードから[y]キー→[Enter]キーを押してください。

インストールして良いかの確認プロンプトが表示されるので[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

より新しいバージョンが存在するパッケージ一覧を表示する

アップグレードが存在する場合は早めにapt upgradeを実行しておこう

Ubuntuを使っていくと「このパッケージ、インストールされていたっけ?」となるシーンがよくあります。そのようなときは「apt list」で確認してみましょう。

パッケージの内容の確認

Debパッケージを操作する「dpkg」コマンドを使えば、個々のパッケージをより詳細に管理できます。冒頭で「パッケージには実行バイナリやドキュメント、画像等のリソースが含まれている」と説明しました。それでは、あるパッケージ内にはどのようなファイルが含まれているのでしょうか。これを調べたいときは「-L」オプションを付けてdpkgコマンドを実行します。引数にはインストール済みの調査したいパッケージ名を指定してください。以下のコマンドでは、Linuxで使われる基本的なコマンド群を提供しているGNU Coreutilsのパッケージの内容を調べることができます。

$ dpkg -L coreutils

coreutilsパッケージに含まれるファイル一覧を表示する

coreutilsパッケージには/usr/bin/以下にインストールされるコマンドが含まれていることが分かる

逆に、システム上にインストールされたあるファイルが、どのパッケージに所属しているかを知りたいこともあるでしょう。こういうときは「-S」オプションを付けてdpkgコマンドを実行します。引数には調べたいファイルをフルパスで指定してください。以下のコマンドでは、ファイルの結合や表示に使う「cat」コマンドが、どのパッケージからインストールされているかを調べます。

$ dpkg -S /usr/bin/cat

catコマンド(/usr/bin/cat)が含まれているパッケージを調べる

/usr/bin/catコマンドはcoreutilsパッケージで提供されていることが分かる

「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のライフサイクルに縛られてしまう」という問題もあります。そこで次回は、この問題を解決する「ユニバーサルパッケージ」について解説します。

日本仮想化技術株式会社
Ubuntu Japanese Teamメンバー。理想のフリーデスクトップ環境を求めて東へ西へ……のはずが,気がついたら北の大地で就職していたインフラ寄りのエンジニア。最近レンズ沼にハマる。日本仮想化技術株式会社所属。

連載バックナンバー

開発ツール技術解説
第3回

「Ubuntu」のパッケージ管理を学ぼう

2024/12/4
第3回の今回は、WSL上のUbuntuを活用する上で必須となる、パッケージの管理方法について解説します。
開発ツール技術解説
第2回

「Windows Terminal」を使いこなす

2024/11/20
第2回の今回は、実際にWSLを操作するCLIについて、その使い勝手を決めるターミナル「Windows Terminal」の操作方法について解説します。
開発ツール技術解説
第1回

「WSL2」をインストールしよう

2024/10/30
第1回の今回は、Windows 11上でLinux環境を実行する機能「WSL」(Windows Subsystem for Linux)のインストール方法を解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています