Docker Desktopとは
最近のトレンドのひとつに「コンテナ」があります。高速に独立したアプリケーション実行環境を作れる「Docker」は、アプリ開発者からシステム運用者まで、幅広く活用されているソフトウェアです。
DockerをMacやWindows上で簡単に扱えるよう、Dockerデーモン、CLIコマンド、GUIフロントエンド等々とあわせてパッケージングしたプロダクトが「Docker Desktop」です。そのDocker Desktopが、最近ついにLinuxに対応しました 。
Dockerなら昔からLinux上で動くし、パッケージも用意されているし、別にGUIとかいらないし、何の意味があるかわからないよ……という方も多いでしょう。またDocker Desktopが有料化されたというニュースを聞いて、抵抗を感じる方もいるかもしれません。
結論から言ってしまうと、Docker Desktopを使うメリットのひとつは、ホスト環境ごとの違いをなくせる点です。Docker DesktopはWindows/Mac/Linux版が存在しますが、機能的な違いはありません。そのため開発者の使用するOSが混在しているような環境でも、バージョンを揃えるだけで、手軽に共通の開発環境を整えることができます。そしてDocker Desktopが有料化されたのは事実ですが、中小企業や個人用途であれば、現在でも無料で使えます。こう聞くと、なんだか魅力的に見えてくるのではないでしょうか。
それではUbuntu上でDocker Desktop for Linux(以下DD4L)を使う具体的な方法を、その機能と合わせて詳しく紹介していきましょう。
Ubuntu 22.04 LTSにDD4Lをインストールする
まずベースとなるUbuntu 22.04 LTS環境を用意しましょう。DD4Lの動作に必要な環境は以下の通りです。現在のUbuntuデスクトップが動作しているのであれば、特に問題となる箇所はないでしょう。
仮想化支援機能を搭載した64bit CPU
64bitカーネル
Kernel-based Virtual Machine(KVM)
QEMU バージョン5.2以降
systemd
GNOMEもしくはKDEデスクトップ環境
4GB以上のメモリ
なぜコンテナを動かすのにKVM?と思うかもしれません。実はDD4Lはホストマシン上で直接ではなく、仮想マシンを作成した上で、その中でDockerデーモンを動作させます。これは、WindowsやMac上のDocker Desktopとの差異をなくすためや、LTSバージョンのOS上でも最新のカーネルの機能を提供するためなど、いくつかの理由によるものです。詳しくは公式ドキュメントのWhy Docker Desktop for Linux runs a VM を参照してください。QEMUのバージョン5.2以降が要求されているのは、virtiofsが必要な都合上です。QEMUのバージョンが4.2のUbuntu 20.04 LTSでも、DD4Lは起動することはします。しかし正式にサポートされているバージョンではないため、22.04 LTSの利用を強く推奨します。
なおDocker用の仮想マシンを動かさなくてはならない都合上、DD4LのホストとなるUbuntu自体が仮想マシン内で動作している場合は、Nested VMを有効にする必要があります。例えばVirtualBoxであれば、VirtualBoxのホスト上で以下のコマンドを実行して、ネステッドVT-x/AMD-Vを有効化してください。
ネステッドVT-x/AMD-Vを有効化する
$ VBoxManage modifyvm 'VM名' --nested-hw-virt on
DD4Lは、公式が提供しているUbuntu向けのDebパッケージからインストールできます。ただしDD4Lはdocker-ce-cliパッケージに依存しているため、インストールに先立って、Dockerの公式リポジトリを追加しておく必要があります。以下のコマンドを実行して、リポジトリ鍵とAPTラインを追加してください。
依存パッケージをインストールするため、Docker公式のリポジトリを追加しておく
$ sudo apt update && sudo apt install -y curl
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt update
ダウンロードページ を開き、Debパッケージをダウンロードしてください。本記事執筆時点(2022年6月)では、バージョン4.9.0が最新でした。ダウンロードしたファイルをaptコマンドでインストールします。
図1 DD4LのDebパッケージをダウンロードする
docker-desktopパッケージのインストール
$ sudo apt install ./docker-desktop-4.9.0-amd64.deb
DD4Lの起動とコンテナの管理
インストールが完了したら、Superキーを押して「docker」と検索し、DD4Lを起動してください。
図2 DD4Lの起動
初回起動時は図3 のような利用規約への同意画面が表示されます。DockerにはDocker Subscription Service Agreementというサブスクリプションサービス契約があり、Docker Desktopはこの影響を受けるプロダクトです。簡単に言えば、Docker Desktopは個人や中小企業での利用であれば無料ですが、一定の規模以上の企業で利用するのであれば、有償のサブスクリプション契約が必要になります。詳細は公式ブログ を参照してください。
図3 Docker Subscription Service Agreementを確認した上で同意する必要がある
問題がなければ「I accept the terms」にチェックを入れた上で、「 Accept」をクリックしてください。DD4Lが起動すると、図4 のような画面が開きます。
図4 DD4Lのホーム画面
それでは実際にコンテナを起動してみましょう。ホーム画面にいくつか定番のコンテナイメージがリストアップされています。ここではUbuntuのイメージの「Run」をクリックしてみましょう。すると自動的にリポジトリからUbuntuのイメージがPullされ、コンテナインスタンスが起動します。
図5 Ubuntuコンテナが起動した状態。Launch terminalをクリックするとコンテナ内のシェルを取ることができる
図6 裏側で動作しているのは普通のDockerのため、dockerコマンドで直接操作することもできる。これはdocker execを実行してターミナルからコンテナのシェルを取った例
別のコンテナも起動してみましょう。今度はホーム画面から、NGINXのイメージの「Run」をクリックしてみます。すると図7 のようなダイアログが表示されます。
図7 NGINXコンテナ起動時に表示されるダイアログ。NGINXで公開するホスト上のディレクトリを指定する
NGINXはWebサーバーですから、コンテンツを公開するディレクトリが必要になります。ここで指定したホスト上のディレクトリをコンテナ内にマウントし、Webサーバーで公開できるという仕組みです。例えば以下のコマンドを実行し、~/www
ディレクトリ内に「hello, world」とだけ書かれたファイルを用意し、コンテナにマウントしてみます。
ディレクトリを作成し、シンプルなHTML(という名のテキスト)を用意してみた
$ mkdir ~/www
$ echo 'hello, world' > ~/www/index.html
コンテナが起動すると、今度はOverviewにURLが表示されました。このURL(localhost:55000)で、コンテナ内のNGINXにアクセスできます。
図8 NGINXコンテナが起動した状態。コンテナの標準出力に出力されている、サーバーのアクセスログが表示されている
図9 http://localhost:55000にホストマシンのブラウザからアクセスした例。先ほど作成したindex.htmlが表示されているのがわかる
左ペインから「Containers」をクリックすると、現在起動中のコンテナの一覧を表示できます。ここからコンテナの停止や再起動、削除といった管理が可能です。
図10 動作中のコンテナの一覧。UbuntuコンテナとNGINXコンテナが起動しているのがわかる
「Images」をクリックすると、ローカルに存在するコンテナイメージを表示できます。ここではイメージのPullやリモートリポジトリへのPush、不要になったイメージの削除といったイメージの管理全般を行えます。イメージ名の右側に表示されているケバブメニューから「Inspect」をクリックすると、そのイメージがどのようにビルドされたかの履歴を確認できます。DockerHubへサインイン済みの場合は、リモートリポジトリの内容も参照できます。そして当然ですが、ここからイメージを選択してコンテナインスタンスを起動することもできます。
図11 イメージの一覧を表示した例。先ほど起動した際にPullされた、UbuntuとNGINXのイメージが確認できる
図12 NGINXイメージの履歴を表示した例
docker-composeを使う
DD4Lでは、デフォルトでCompose V2が使えます。docker-compose.ymlを用意して、「 docker compose」コマンドを実行すれば、WebアプリコンテナとDBコンテナといった、複数のコンテナを簡単に管理できます。
注意点としては、Compose V1である従来の「docker-compose
」コマンドはインストールされていない点です。互換性の都合といった理由で、どうしてもdocker-compose
コマンドを使いたい場合は、設定の「General」 →「 Enable Docker Compose V1/V2 compatibility mode」にチェックを入れてください。/usr/local/bin
以下に、dockre-composeというシンボリックリンクが作成されます(ただし内部的にはdocker composeコマンドを呼び出します) 。
図13 docker composeコマンドで起動したコンテナ群は、GUI上からもグループ化されて見える。一度コンテナを作成してしまえば、以後はGUI上からまとめて起動や停止が可能になる
Kubernetesを動かす
コンテナの話題となれば、みんな大好きKubernetes(以下k8s)は欠かせません。とはいえ自前できちんとしたk8s環境を構築するのはなかなか手間ですし、かといってAWSのEKSやGCPのGKEは、クラスターを維持するだけで結構な料金がかかりますよね。
手軽なお試し環境でよければ、過去にも紹介したように、snapパッケージのmicrok8s を使うのが簡単です。ところがDD4Lを使えば、もっと簡単にk8s環境を用意できます。というのもDD4Lにはk8sがビルトインされており、設定のGUIからチェックを入れるだけで、シングルノードクラスターを自動的に起動させることができるのです。
ウィンドウ右上の歯車アイコンをクリックして、「 Kubernetes」を開いてください。「 Enable Kubernetes」にチェックを入れてから「Apply & Restart」をクリックすると、k8sが起動します。
図14 デフォルトでは、k8sのシステムコンテナ(kube-proxyやcorednsなど)はDD4Lのコンテナ一覧には表示されない。「 Show system containers」にチェックを入れることで表示させることもできるが、自分で起動したコンテナの見通しが悪くなるため、やらないほうがいいだろう
図15 DD4Lのコンテナ一覧には表示されないが、docker psを実行すると、k8s関連のコンテナが起動しているのがわかる
この段階でホームディレクトリ内の「~/.kube/config
」にKUBECONFIGが作成されます。そのためkubectlコマンドをインストールするだけで、DD4L上のk8sクラスターを操作可能です。kubectlコマンドは、snapを使ってインストールするのが簡単でしょう[1] 。
ただし、k8sクラスターとkubectlコマンドのバージョンの違いには注意してください。DD4L 4.9.0では、k8s 1.24.0のクラスターがデプロイされます。DD4Lのバージョンが上がっていくと、新規にデプロイされるクラスターのバージョンもその時期に応じて上がっていきますが、デプロイ済みのクラスターは自動的にアップグレードされません。そのためkubectlをデフォルトの「latest/stable」チャンネルからインストールしてしまうと、snapパッケージの自動更新によって、クライアントとクラスターのバージョンが乖離してしまう可能性があります。この問題を防ぐためには、kubectlのリリースチャンネルを明示的に指定して、バージョンを揃えるのがお勧めです。
リリースチャンネルを1.24/stableに指定してインストールする例と、インストール済みのkubectlのチャンネルを変更する例
$ sudo snap install kubectl --channel=1.24/stable --classic
$ sudo snap switch kubectl --channel=1.24/stable
図16 kubectlコマンドの実行例。docker-desktopというノード1台で構成され、kube-system名前空間にPodが起動しているのがわかる
実際にk8s上にサービスを起動してみましょう。ここでは例として、HTTPのリクエストをそのまま表示する「echoserver」を起動してみます。まず以下の内容で「echoserver.yml」というマニフェストファイルを作成してください。
echoserverのマニフェスト
apiVersion: v1
kind: Namespace
metadata:
labels:
app: echoserver
name: echoserver
---
apiVersion: v1
kind: Service
metadata:
labels:
app: echoserver
name: echoserver
namespace: echoserver
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: echoserver
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: echoserver
name: echoserver
namespace: echoserver
spec:
replicas: 2
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- image: gcr.io/kubernetes-e2e-test-images/echoserver:2.2
imagePullPolicy: Always
name: echoserver
ports:
- containerPort: 8080
続いて以下のコマンドで、マニフェストを適用します。
kubectl apply
コマンドでマニフェストをクラスターに適用する
$ kubectl apply -f echoserver.yml
kubectlコマンドを使って、echoserver名前空間内にふたつのPodと、NodePortのサービスが作成されていることを確認します。
図17 割り当てられているポート(ここでは31367)はブラウザからのアクセスに必要になるため、覚えておく
Webブラウザを開き、「 http://localhost:(サービスのポート)」にアクセスしてください。echoserverの画面が表示されれば成功です。
図18 echoserverにブラウザからアクセスした画面。リクエストの情報やリクエストヘッダが表示される
このようにDD4Lを使えば、簡単にシングルノードのk8sクラスターを用意できます。ローカルでのテストやデバッグに役立つのではないでしょうか。
別のDockerデーモンとの共存について
DD4Lは、仮想マシン内の独立した空間でDockerデーモンを起動します。そしてDD4Lは、ホストマシン上に直接インストールされた、別のDockerデーモンと共存させることができます。
Dockerには「コンテキスト」と呼ばれる仕組みが存在します。コンテキストにはDockerデーモンのエンドポイントをはじめとする情報が含まれており、このコンテキストを切り替えることで、ひとつのdockerコマンドから、複数のバックエンドを選択して操作することができるのです。
通常Dockerをインストールすると、エンドポイントがローカルのunix:///var/run/docker.sock
というソケットを向いた、defaultという名前のコンテキストが作成されます。対してDD4Lは、インストール時にdesktop-linuxという名前で、エンドポイントがホームディレクトリ内の「~/.docker/desktop/docker.sock
」を向いた専用のコンテキストを作成します。そしてDD4Lは、起動時にdockerコマンドがdesktop-linuxコンテキストを利用するよう切り替え、終了時にはdefaultコンテキストに切り戻すという動作を行います。そのためホスト上で別のDockerデーモンが動作していても、DD4Lの起動中のみ、dockerコマンドはDD4LのDockerデーモンと対話するようになるのです。
とはいえ複数のDockerデーモン自体は共存できると言っても、当然コンテナはそれぞれで別管理となるため、どんなコンテナが起動しているかの見通しが悪くなるといったデメリットもあります。起動したコンテナがホストのポートを奪い合うといったトラブルも起きがちですので、筆者としてはあまりお勧めしません。日常的にDD4Lを使うのであれば、ホスト上のDockerデーモンは停止するか、アンインストールしてしまうほうが安心でしょう。
DD4L起動中にdocker context list
コマンドを実行した例。desktop-linuxコンテキストに切り替わっていることがわかる。
$ docker context list
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
desktop-linux * moby unix:///home/mizuno/.docker/desktop/docker.sock
なおパッケージの依存関係の都合上、本記事の手順でインストールしたDD4Lと、Ubuntuが提供しているdocker.ioパッケージを共存させることはできません。共存させたい場合はDocker公式が提供しているdocker-ceパッケージを利用してください。
Docker Extensionsを利用する
Docker Desktopを使うメリットのひとつが、Docker Extensionsです。現時点ではまだベータ版の機能ではあるもの、サードパーティ製のツールを追加することで、Docker Desktopの機能を拡張できます。
左ペインの「Add Extensions」をクリックしてください。MarketplaceにあるExtensionsの一覧が表示されますので、インストールしたいExtensionsの「Install」ボタンをクリックしてください。
図19 ExtensionsのMarketplaceの画面。ここからインストールしたいExtensionsを探してInstallボタンをクリックする。ただしまだExtensionsの数は少ない
筆者が便利だなと思ったExtensionsが、「 Logs Explorer」です。通常コンテナのログを確認しようと思うと、「 docker ps
」でコンテナIDを調べ、「 docker logs
」コマンドを実行する必要があります。ログをtail
したければ、-f
オプションをつけて、ターミナルを開きっぱなしにしなければなりません。負荷分散のために複数のNGINXコンテナを起動しているような場合は、すべてのコンテナのアクセスログを束ねて監視したいですよね。そうなるともう面倒くさすぎます[2] 。
Log Explorerは、起動中のコンテナのログを横断的に検索できるExtensionsです。複数コンテナのログを時系列に並べて一括表示できるだけでなく、コンテナ単位での絞り込み、キーワード検索、標準出力/標準エラー出力でのフィルタが可能です。
図20 Logs Explorerの画面。docker logsコマンドを使ったことがある人であれば、これだけで便利さが理解できると思う
「Disk Usage」Extensionsは、Dockerが利用しているディスク容量を可視化してくれます。「 Reclaim space」ボタンをクリックすると、停止しているコンテナや不要なイメージ、ボリューム、ビルドキャッシュなどを選択して削除できます。
図21 Disk Usageの画面。ディスク容量が逼迫したような場合は、不要なデータが多く溜まっていないかチェックしてみるとよいだろう
「Anchore」Extensionsは、コンテナイメージの脆弱性をチェックできます。コンテナのセキュリティを高めるためにも、自分でビルドしたイメージはもちろん、DockerHubから入手したイメージのチェックに役立ててみてください。
図22 ローカルに保存されているコンテナイメージの一覧が、インストールされているパッケージと、脆弱性の数とともに表示される
図23 特定のイメージ名をクリックすると、パッケージ名、パッケージバージョンとともに、影響するCVEと緊急度も確認できる