PortainerでDockerをUIから管理する — コマンドを覚えなくて済む、ミスも怖くない

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

毎日Dockerコマンドを打ち続ける — そろそろ疲れる

VPS上で数十のコンテナを動かしているなら、おなじみのルーティンができているはずだ。SSHでサーバーに接続し、docker ps -aを打って大量のコンテナを眺め、一つひとつのログを手探りで確認する。次はdocker inspectでネットワークやボリュームをチェック。ちょっとした操作でもターミナルを開かなければならない。

自分もそういう時期があった。最初は5〜6個のコンテナで、コマンドも覚えられた。でも20〜30個 — Nginx、PHP-FPM、MySQL、Redis、n8n、Gitea — と増えてくると、CLIが重荷になってくる。特に深夜2時のデバッグ中、目が霞んでコンテナ名を打ち間違えるのは珍しくない。

Docker CLIだけでは実運用に限界がある理由

Docker CLIが弱いのではない。むしろCLIは非常に強力だ — ただし、コンテナ名、ボリューム名、コマンドの構文を正確に覚えている必要がある。実際に感じた痛点をいくつか挙げると:

  • 全体把握が難しい:docker statsはリアルタイム表示だが、履歴は残らず、グラフもない。
  • 権限共有が面倒:同僚にログを見せたいだけなのに、SSHキーを発行しなければならない — 不必要なリスクだ。
  • 操作ミスが起きやすい:稼働中のコンテナをdocker rmで誤って削除するのは、思っているより頻繁に起こる。
  • ネットワークのトポロジーが見えない:CLIだけではどのコンテナがどのネットワークに接続しているか把握しにくい。

そこで代替手段を探し始めた — Docker Engineの上に乗っかって、細かい操作のたびにターミナルを開かずに済むものが必要だった。

DockerをGUIで管理するための選択肢

Lazydocker — シンプルなターミナルUI

Web UIを入れたくない人には、Lazydockerが最も軽量な選択肢だ。ターミナル上でそのまま動き、ポートも不要、リバースプロキシも要らない。デメリット:サーバーにSSHしなければならず、リモートからのアクセスが不便。

Rancher — 重量級、Kubernetes向け

Rancherは強力だが、主にKubernetesクラスタ向けの設計だ。スタンドアロンDockerだけを使うなら、Rancherはオーバーキル — RAMを食い、設定が複雑で、立ち上げに半日かかる。

Portainer CE — シンプルさと実用性のちょうどいいバランス

Portainer Community Editionは2年間使い続けて、乗り換える理由が見つかっていない。Dockerでインストールし、Webブラウザからアクセスでき、コンテナ/イメージ/ボリューム/ネットワークを一通り管理できる。特にUIから直接Docker Composeスタックを管理できる機能が便利で — SSH不要でデプロイできる。

Portainerのインストール — 後で困らない正しいやり方

インストール前の要件

  • Docker Engineがインストール済み(バージョン20.10以上)
  • Docker Compose v2(統合プラグイン版、スタンドアロンのv1ではない)
  • VPS/サーバーでポート9443(HTTPS)または9000(HTTP)が開放されていること

ディレクトリとComposeファイルの準備

自分はいつもDocker ComposeでPortainerをインストールする — docker runを直接使うよりも、アップデート・バックアップ・マイグレーションが楽だ。注意点:docker compose(v2、ハイフンなし)を使うこと。旧来のdocker-composeではない。より高速で、最新のDocker Engineとの統合も優れており、docker-compose v1は2023年7月に正式にend-of-lifeとなっている。

mkdir -p /opt/portainer && cd /opt/portainer

次の内容でcompose.ymlファイルを作成する:

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9443:9443"
      - "8000:8000"   # トンネルエージェント(オプション)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

volumes:
  portainer_data:

Portainerの起動

docker compose up -d

コンテナが起動しているか確認する:

docker compose ps

10〜15秒後、ブラウザでhttps://<IP-server>:9443にアクセスする。初回はadminアカウント作成フォームが表示されるので、情報を入力してログインする。

注意:Portainerは自己署名証明書を使用するため、ブラウザが警告を表示する。「Advanced → Proceed」をクリックしてスキップするか、後でLet’s Encryptを使ったリバースプロキシを設定することを推奨(本番環境向け)。

初期セキュリティ設定 — このステップを省略しないこと

adminアカウントを作成したら、使い始める前に以下の設定をすぐに行うこと:

  1. 強力なパスワードを設定する — 最低12文字以上、数字と特殊文字を含めること。
  2. 不要なアクセス権を無効化する:Settings → Authentication → 自分だけが使う場合は「Allow non-admin users to access the local environment」をオフにする。
  3. ファイアウォールでIPを制限する:自分のIPだけがポート9443にアクセスできるようにする。
# 特定のIPアドレスのみPortainerへのアクセスを許可する
ufw allow from 203.0.113.10 to any port 9443
ufw deny 9443
ufw reload

インストール後の実践的なTips

UIからDocker Composeスタックを管理する

自分が一番使う機能だ。Stacks → Add stackに進み、デプロイしたいサービスのcompose.ymlの内容を貼り付けるだけ — Portainerが一つのユニットとして管理してくれる。新しいイメージへの更新が必要なら、「Pull and redeploy」をクリックするだけで完了。SSH不要、コマンドを覚える必要もない。

コンテナ名を覚えなくてもリアルタイムでログを確認する

コンテナをクリック → Logsタブ → 「Auto-refresh logs」にチェックを入れるだけ。デバッグのたびにdocker logs -f --tail 100 very-long-container-nameと打つより、はるかに便利だ。

ブラウザからコンテナにExecする

Container → Consoleタブ → Connect。ターミナルがブラウザ上で直接開くため、SSHウィンドウを追加で開く必要がない。コンテナ内の設定ファイルをサクッと確認したいときに重宝する。

ボリュームのバックアップが楽になる

Volumesページに移動すると、どのコンテナがどのボリュームを使っているか一目瞭然だ。ボリュームを素早くバックアップするスクリプト:

# portainer_dataボリュームをtarファイルにバックアップする
docker run --rm \
  -v portainer_data:/source \
  -v /backup:/dest \
  alpine tar czf /dest/portainer_data_$(date +%Y%m%d).tar.gz -C /source .

データを失わずにPortainerをアップデートする

Composeでインストールし、データはnamed volumeに保存されているため、アップデートは非常に安全だ:

cd /opt/portainer
docker compose pull
docker compose up -d

本番環境向けNginxリバースプロキシの設定

すでにNginxが動いているなら、自己署名証明書の代わりに正式なHTTPSを使えるよう、Portainerをリバースプロキシの後ろに置くことを推奨する:

server {
    listen 443 ssl;
    server_name portainer.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/portainer.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/portainer.yourdomain.com/privkey.pem;

    location / {
        proxy_pass https://localhost:9443;
        proxy_ssl_verify off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

その後、compose.ymlportsセクションを削除する — ポート9443は外部に公開されなくなり、内部のNginxのみが接続できる。

Portainerを使わない方がいい場面

Portainerがすべての答えではない。慎重に検討すべきケースもある:

  • 自動化されたCI/CD環境:デプロイパイプラインにUIは不要 — CLIやDocker APIを直接使う方がシンプルで依存も少ない。
  • 高いセキュリティ要件のサーバー:/var/run/docker.sockをPortainerコンテナにマウントするということは、Portainerがホスト上のroot権限を持つということだ。厳格な本番環境では、ソケットを直接マウントする代わりにPortainer Agentの使用を推奨する。
  • Kubernetesクラスタ:PortainerはK8sもサポートしているが、純粋なKubernetes環境にはLensやk9sの方が適している。

個人のVPSや小規模チームでスタンドアロンDockerを運用するなら、Portainerは最も導入価値の高い選択肢だ。セットアップに半日投資するだけで、毎日長いコマンドを打つ手間がなくなる — かなりいいトレードオフだと思う。

Share: