Ubuntu 26.04 講座 / コンテナアプリの実行とデータ・ポートの管理

コンテナアプリは、イメージで実行環境を作りますが、永続データと公開ポートは別に管理する必要があります。この実習では、Ubuntu 26.04専用VMでDocker EngineとComposeをインストールし、Dockerを動かすVM内からのみアクセスするNginxアプリのデータをコンテナ再生成後も保持する方法を扱います。

導入方法と権限を決める

既にDocker・containerd・Kubernetesを使用しているサーバーでは、パッケージを削除したり導入方法を混在させたりしません。既存のコンテナ・ボリューム・ストレージを調査して、別途変更計画を立ててください。以下はDockerリポジトリがまだない新しいUbuntu VM用の手順で、既存の /etc/apt/sources.list.d/docker.sources と /etc/apt/keyrings/docker.asc がある場合は実行しません。

DockerのUbuntuインストールドキュメントで、26.04対応、競合するパッケージやリポジトリのインストール手順を確認できます。

dockerグループとDockerソケットのアクセス権は、ホストに非常に強い権限を与えます。この記事では必要なコマンドにsudoを明記しており、ソケットに777権限を与えたり、すべてのユーザーをdockerグループに追加したりしません。信頼できないイメージを実行することは、単にファイルを開く操作とは異なります。

公式リポジトリからインストールする

次の全コードを ~/install-docker-lab.sh に保存し、bash ~/install-docker-lab.sh で実行します。Ubuntu 26.04 の確認と既存ファイルの検査に失敗した場合、書き込む前に中断します。リポジトリキーは該当リポジトリにのみ Signed-By で接続します。

set -eu
. /etc/os-release
if [ "$ID" != ubuntu ] || [ "$VERSION_ID" != 26.04 ]; then
    printf "This lab requires Ubuntu 26.04.\n" >&2
    exit 1
fi
if [ -e /etc/apt/sources.list.d/docker.sources ] || [ -e /etc/apt/keyrings/docker.asc ]; then
    printf "Inspect the existing Docker repository first.\n" >&2
    exit 1
fi
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: ${UBUNTU_CODENAME:-$VERSION_CODENAME}
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker version
sudo docker compose version
sudo docker run --rm hello-world

インストールが終わったら、クライアント・サーバーのバージョンと hello-world の成功メッセージを確認します。失敗した apt・署名・ネットワークエラーは無視せず、次のステップに進みません。実際のインストールバージョンは運用記録に残し、リポジトリを削除してもインストールされたエンジンやデータは消えません。

Nginx サイト構成の例では 8080 を維持し、コンテナのホストポートは 8081 に分離します。コンテナ内部の 80 は維持します。8081 も使用中の場合は ss と compose ps で所有者を確認し、他の検証済みポートを Compose・curl の例全体で一貫して使用します。

Compose ファイルとボリュームを作成する

新しい ~/compose-lab ディレクトリを作成し、その中に compose.yaml を以下の内容で保存します。127.0.0.1:8081 が空いているかどうかは、まず ss -lnt で確認します。ports の前のアドレスを省略すると他のインターフェースにも公開される可能性があるため、実習では明示的にループバックを使用します。

services:
  web:
    image: nginx:stable-alpine
    ports:
      - "127.0.0.1:8081:80"
    volumes:
      - lab-html:/usr/share/nginx/html
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
volumes:
  lab-html:

lab-html はコンテナの書き込みレイヤーとは別の名前付きボリュームです。初期コンテンツから開始し、この実習の index.html を記録します。stable-alpine タグが指すイメージは変更される可能性があるため、再現可能な運用には検証済みのダイジェストと更新手順が必要です。サンプルログの制限もサービス負荷に合わせて調整します。

実行・再生成・データ保持の確認

(
set -eu
cd ~/compose-lab
sudo docker compose config
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
sudo docker compose logs --tail 30 web
)

設定の確認とイメージのダウンロードが成功した後に実行します。コンテナが実行中かどうかとログを確認し、以下の実習内容を記録します。運用データがある既存プロジェクトやボリュームの例示ファイルを上書きしません。

(
set -eu
cd "$HOME/compose-lab"
sudo docker compose exec web sh -c 'printf "volume-lab\n" > /usr/share/nginx/html/index.html'
curl --fail http://127.0.0.1:8081/
sudo docker compose up -d --force-recreate
curl --fail http://127.0.0.1:8081/
sudo docker image inspect nginx:stable-alpine --format '{{json .RepoDigests}}'
)

実行・再生成・終了の各コードブロックは ~/compose-lab に移動した後に実行します。括弧内の作業フォルダ変更はブロックが終了すると保持されません。すべての Compose コマンドが同じ compose.yaml を使用する必要があり、同じプロジェクトとボリュームを扱います。再生成の前後での応答がどちらも volume-lab であれば、同じボリュームのファイルを読んだことになります。これはバックアップの成功やアプリケーション全体の正常動作を証明するものではありません。他のデバイスからはこのループバック公開ポートに接続できないことを確認し、ホストの実際のバインディングも ss や docker compose ps で確認します。

Docker のポート公開とファイアウォールのドキュメントを確認してください。公開ポートは UFW のルールだけで保護されるとは考えてはいけません。

停止とデータ削除の区別

(
set -eu
cd "$HOME/compose-lab"
sudo docker compose down
sudo docker volume ls
)

down はこのプロジェクトのコンテナ・ネットワークを整理しますが、名前付きボリュームは基本的に残ります。再度 up -d をした後に同じ応答が出るか確認できます。down -v や volume prune はデータを削除する可能性があるため、単純な終了コマンドとしては使用しません。ボリュームのバックアップはアプリの書き込みを調整し、別の保存場所で復元試験まで行う必要があります。