🖥️

【3-1】Docker入門編!なぜコンテナが必要か?UbuntuへのインストールとAD連携Sudo沼

に公開

はじめに

前回の記事では、Proxmox VEによる仮想化基盤を構築し、Windows ServerでActive Directoryを立ち上げ、Ubuntu Serverをドメインに参加させるというハイブリッド環境の基礎を固めてきました。いよいよ、現代のアプリケーション開発・運用に欠かせない技術であるDockerの学習にステップインします!
https://zenn.dev/koikoi_infra/articles/13b5b4cb70921d

この記事では、これまでの学習の総仕上げとして、ドメインに参加したUbuntu Server上にDocker環境を構築するプロセスを記録します。Dockerの基本的な概念の整理から、具体的なインストール手順、そしてAD連携環境ならではの「Sudo沼」にハマり、解決するまでの道のりを共有します。

今回のゴール

Dockerとは何か? - 3つのキーワードで理解する

Dockerが解決する「環境が違うと動かない問題」

まず、なぜDockerが必要とされているのでしょうか?それは、多くの開発者が経験する「自分のPCでは動いたのに、サーバーに持っていくと動かない…」という問題を解決するためです。

この問題は、OSのバージョンの違い、インストールされているライブラリの違い、設定ファイルの記述ミスなど、開発環境と本番環境のわずかな「環境の差異」によって引き起こされます。

解決策は「アプリと環境のパッケージ化」

Dockerは、この問題を解決するために非常に賢いアプローチをとります。それは、「アプリケーション本体」と、そのアプリが動くために必要な「OSのライブラリや設定ファイルなどの実行環境」を、丸ごと一つのパッケージにしてしまうというアイデアです。

このパッケージを、開発PCでも本番サーバーでも同じように動かすことで、「環境の差異」そのものを無くしてしまおうというわけです。そして、この仕組みを実現するために、Dockerには3つの重要なキーワードが登場します。

パッケージ化を実現する3つの要素

1. Dockerfile:アプリの動かし方を書く「レシピ」

まず、Dockerは「どういう環境で、どういう手順でアプリを動かすか」を記述した設計図を必要とします。これがDockerfileと呼ばれるテキストファイルです。料理に例えるなら、これは「レシピ」そのものです。

2. イメージ:どこでも同じ味が再現できる「ミールキット」

次に、Dockerfile(レシピ)をもとに、実際にアプリケーションを実行できる状態のパッケージを作成します。これが「イメージ」です。これは、レシピをもとに材料がすべて揃えられ、下ごしらえまで済んだ「ミールキット」のようなものです。このイメージさえあれば、誰がどこで作っても同じ品質のものが出来上がります。

3. コンテナ:実際に動いている「料理」

最後に、出来上がった「イメージ」(ミールキット)を実際に動かします。この、実行中の状態が「コンテナ」です。これは、ミールキットを調理して食卓に出された「出来上がった料理」です。

この「Dockerfile → イメージ → コンテナ」という流れが、Dockerの基本です。

改めて、これまでに学んだVMやLXCと比較すると、その目的の違いが明確になります。

項目 仮想マシン (VM) コンテナ (LXC) コンテナ (Docker)
仮想化対象 OS全体 軽量なOS環境 アプリケーションと実行環境
主な目的 別のOSを動かす 軽量なLinuxサーバー アプリをどこでも同じように動かす
例えるなら 一戸建て マンション 目的特化型のカプセル家電

Ubuntu ServerへのDocker環境構築

それでは、このDockerの仕組みを、ドメインに参加済みの ubuntu-server-01 (192.168.3.101) にインストールしていきましょう。

Step 1: システムの更新と準備

adm-labuserでSSH接続し、システムを最新化します。Dockerのインストールに必要なツールも併せて導入します。

# パッケージリストの更新とアップグレード
sudo apt update && sudo apt upgrade -y

# 必要なツールをインストール
sudo apt install -y curl wget gnupg lsb-release
AD連携環境でのSudo沼脱出記

実は、上記コマンドの初回実行時、AD連携環境ならではの大きな壁にぶつかりました。sudoを実行すると、adm-labuser is not in the sudoers file.という無情なエラーが表示されたのです。

以前、ADのIT-Administratorsグループにsudo権限を付与したはずなのに、なぜ...?

原因調査の道のり

AD側の確認: まずはドメインコントローラー(ws01)で、adm-labuserがIT-Administratorsグループに所属しているか確認しました。
→ 結果: 問題なく所属。AD側の設定は正しい。

Linux側の認識確認: 次にUbuntu側がグループ所属を正しく認識しているか、idコマンドで確認しました。

id adm-labuser
uid=... gid=... groups=...,1628401111(it-administrators)

→ 結果: なんと、it-administratorsとして正しく認識されている!連携は成功していました。

sudoersファイルの設定確認: 連携が正しいなら、sudoの設定ファイル自体が怪しいと判断。ローカル管理者(labsuser)でログインし直し、sudo visudoで設定を確認しました。

# ...
%IT-Administrators@koikoi_infra.local ALL=(ALL:ALL) ALL

→ 原因判明!ここに2つの問題が潜んでいました。

大文字/小文字: idコマンドの結果はすべて小文字のit-administratorsでしたが、設定ファイルでは大文字始まりのIT-Administratorsになっていました。Linuxは大文字と小文字を厳密に区別します。

ドメイン名の有無: 我が家の環境では、Ubuntuはグループ名をドメイン名なしの短い形式でsudoに渡していました。

解決策

sudoersファイルを、Ubuntuが実際に認識しているグループ名(小文字、ドメイン名なし)に修正しました。

# ...
%it-administrators ALL=(ALL:ALL) ALL

この修正後、adm-labuserで再ログインし、無事にsudoコマンドが実行できるように。異なるOSを連携させる際の、非常に良い教訓となりました。

Step 2: Docker公式リポジトリの追加とインストール

気を取り直して、Dockerのインストールを続けます。公式の手順に従い、リポジトリを追加していきます。

# Docker公式GPGキーを追加
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Docker公式リポジトリを追加
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Docker Engineをインストール
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

インストール中にサービスの再起動を尋ねる紫色の画面が表示されましたが、これはライブラリが更新されたためで、<Ok>を選択して進めれば問題ありません。

リポジトリとは?apt updateの役割

ここで実行しているコマンドは何をしているのでしょうか?少し寄り道して解説します。

リポジトリとは?
「リポジトリ」とは、ソフトウェアのパッケージ(インストールファイルや設定情報など)を保管している倉庫のようなものです。Ubuntuは、標準で「Ubuntu公式リポジトリ」という巨大な倉庫を持っており、aptコマンドは通常、そこにソフトウェアを探しに行きます。

なぜ新しいリポジトリを追加するの?
Ubuntu公式リポジトリにもDockerはありますが、バージョンが少し古かったりします。常に最新で公式にサポートされたバージョンのDockerを使うために、今回は**「Docker社が公式に運営している専用リポジトリ」**をaptの探し先リストに追加します。

コマンドの役割

  • curl ... | sudo gpg ...: Docker公式リポジトリが本物であることを証明するための「デジタル署名(GPGキー)」をシステムに登録します。これにより、安全なソフトウェアだけをインストールできます。

  • echo "deb [...]" | sudo tee ...: Docker公式リポジトリの「住所(URL)」を、aptの参照リストに書き込んでいます。

  • sudo apt update: これが非常に重要です。このコマンドは、ソフトウェアをインストールするのではなく、aptが持っている「パッケージの品書き(リスト)」を最新の状態に更新する作業です。新しく追加したDocker公式リポジトリにもアクセスし、「うちにはこんなバージョンのDockerがありますよ」という情報をローカルに持ってきてもらいます。

このapt updateを行うことで、初めてaptはDocker社のリポジトリにdocker-ceというパッケージがあることを認識し、次のapt installコマンドで正しくインストールできるようになるのです。

Step 3: 動作確認とsudo不要化設定

最後に、Dockerが正しく動くか確認し、仕上げの設定を行います。

動作確認 (sudoあり)

hello-worldコンテナを実行します。

sudo docker run hello-world

Hello from Docker!というメッセージが表示されればインストール成功です!最初はイメージをネットからダウンロード(pull)するため少し時間がかかります。

もう少し詳しく:コマンドの裏側の流れ

docker run hello-world を実行したとき、内部では以下のことが起きています。

1. コマンドの受付 (クライアント → デーモン)
私たちがターミナルで実行するdockerコマンドは「クライアント」です。この命令は、バックグラウンドで常に動いている「Dockerデーモン(Docker Engine本体)」に送られます。実際にイメージを探したり、コンテナを動かしたりする仕事は、すべてこのデーモンが行います。

2. ローカルイメージの確認
デーモンはまず、「hello-worldという名前のイメージは、すでにこのサーバー(ローカル)にダウンロード済みかな?」と確認します。

3. レジストリへの問い合わせ
ローカルに見つからなかった場合、デーモンは「よし、インターネットから探してこよう」と考えます。ここで、イメージ名 hello-world を解釈します。

hello-world のように、サーバー名/ユーザー名/イメージ名という形式になっていない短い名前の場合、デーモンは設定済みのデフォルトレジストリに問い合わせに行きます。そして、Docker CEをインストールした時点では、このデフォルトレジストリはDocker Hubに設定されています。

Docker Hubとは?:
Docker Hubは、Docker社が公式に提供するコンテナイメージの公開・共有プラットフォームです。GitHubがソースコードを管理するように、Docker Hubはコンテナイメージを管理します。

4. イメージ名の補完
デーモンは、私たちが入力した短い名前を、Docker Hubで通用する完全な名前に内部で補完します。

  • ユーザーが入力: hello-world
  • デーモンが解釈する完全な名前: docker.io/library/hello-world:latest

各部分の意味:

  • docker.io/: デフォルトレジストリであるDocker Hubのサーバー名です。
  • library/: Docker社が公式に管理している優良なイメージが置かれる特別な場所(名前空間)です。これが省略されている場合、デーモンが自動で補ってくれます。
  • :latest: バージョン(タグ)を指定しない場合に、自動で補われる「最新版」を意味するタグです。

5. イメージのダウンロードと実行
デーモンは、この完全な名前を使ってDocker Hubにアクセスし、イメージをダウンロード(pull)してきます。ダウンロードが完了したら、そのイメージを元にコンテナを作成し、実行します。

sudo不要化設定

毎回sudoを打つのは大変なので、adm-labuserをdockerグループに追加します。

# $USERと入力することで現在サインインしているユーザーを指定する
sudo usermod -aG docker $USER

【重要】 この設定を有効にするには、一度ログアウトしてSSHで再接続する必要があります。

最終確認 (sudoなし)

再ログイン後、今度はsudoなしで実行します。

docker run hello-world

同じようにHello from Docker!と表示されれば、全てのセットアップは完了です!

まとめ

今回の学習を通じて、当初の目標を達成することができました。

特に最後のトラブルシューティングは、単に手順をなぞるだけでは得られない貴重な経験となりました。これでようやくコンテナを動かすための土台が整いました。次回からは、このDocker環境を使って実際にWebサーバーなどのアプリケーションを動かしていきたいと思います!

Discussion