本文へ移動
購読
GUIDE#infra更新 2026.09.24

PortainerでDockerをWeb管理する:導入手順と権限・セキュリティの注意点

Portainer CEをDocker Composeで導入し、ブラウザからコンテナやスタックを管理。セットアップトークンと5分の制限、docker.sockの危険性、一般ユーザーの権限の既定値まで実機で確認。

level
初級
time
約25分
stack
Portainer CE 2.45 / Docker Engine / Docker Compose
author
@ryoma_t
// 前提条件
Docker Composeが使えるLinuxサーバーとsudo権限 / 画面を開くPCからサーバーのLAN側アドレスに届くこと
Portainer CE 2.45.1のホーム画面で、local環境がUpになりコンテナ数やCPU・メモリが表示されている画面
画像:nagoya.dev(実際の画面・実行結果をもとに作成)

Portainerとは、Dockerのコンテナ、イメージ、ボリューム、ネットワーク、Composeのスタックを、Webブラウザの画面から一覧・操作できる管理ツールです。ログの確認やコンテナへのシェル接続、compose.yamlの編集と再デプロイまでを1つの画面で行え、Kubernetesの管理にも対応しています。

この記事では、無料のCommunity Edition(CE)2.45.1(執筆時点のLTS版)をDocker Composeで導入します。起動直後のセットアップトークンと5分の制限、Dockerソケットを渡すことの意味、一般ユーザーに与えてよい権限、スタックの扱い方、代替ツールとの使い分けまでを、実際に起動したときのログとAPIの応答をもとに説明します。

この記事でわかること

  • Portainerでできること・できないことと、CEとBusiness Editionの違い
  • /var/run/docker.sock を渡すことが「ホストのroot権限を渡す」のと同じである理由
  • Docker Composeでの導入:公開するポート、HTTPの無効化、データベースの暗号化
  • 初回のセットアップトークン、5分のタイムアウト、12文字以上のパスワード
  • 一般ユーザーの権限の既定値、スタックの管理、パスワードを忘れたときの復旧

Portainerとは:できることと、できないこと

PortainerはDocker Engine APIのクライアントで、docker ps や docker logs、docker compose up でしていたことを画面から行います。コンテナのCPU・メモリの使用状況、環境変数やマウントの確認、コンテナ内のシェル(コンソール)もブラウザで開けるので、コマンドに慣れていないメンバーに「ログを見る」「再起動する」だけを任せたいときに役立ちます。

項目Community Edition(CE)Business Edition(BE)
料金無料・オープンソース有償(条件は公式サイトで確認)
コンテナ・イメージ・ボリューム・スタックの操作できるできる
ユーザーとチーム管理者と一般ユーザーの2種類役割(ロール)を細かく割り当てられる
複数ホストの管理(Agent・Edge Agent)できるできる(Edge向けの機能が多い)

表示言語について補足すると、2.45.1の画面ファイルに含まれる言語データは英語(en)だけでした。日本語化はされていないので、メニュー名はこの記事でも英語のまま書きます。

できないことも押さえておきます。まず、イメージの新しい版を自動で取り込む機能はありませんし、ボリュームの中身をバックアップする機能もありません。また、画面から作ったコンテナの設定は docker run の長いコマンドと同じで、手順として残りません。再現できる形で管理したいサービスは、compose.yamlをGitで管理し、Portainerは状態の確認と日常操作に使う、という分担が安全です。Composeそのものの書き方はDocker Composeで自宅サーバーのスタックを動かすガイドにまとめています。

導入前に知っておく権限の話:docker.sockはroot権限と同じ

PortainerがローカルのDockerを操作するには、ホストの /var/run/docker.sock をコンテナにマウントします。このソケットに書き込める相手は、Docker Engineに何でも命令できます。たとえば特権モードでホストのルートディレクトリをマウントしたコンテナを作れば、ホストのすべてのファイルを読み書きできます。つまり「Portainerの管理者アカウント=ホストのroot」であり、Portainerの画面に入れる人は、そのサーバーの全権を持つ人です。

この前提から、運用のルールは次の3つに絞られます。9443番の画面をインターネットに公開しないこと(外からはTailscaleなどのVPN経由で入る)、管理者のパスワードを強くすること、一般ユーザーを作るなら与える操作を絞ること、です。リバースプロキシを前に置いて画面を外部に公開する構成を見かけますが、画面のログインだけがホストのroot権限を守る壁になるので、家庭でも会社でも避けるべきです。

ソケットを読み取り専用(/var/run/docker.sock:/var/run/docker.sock:ro)でマウントしても、権限は減りません。:ro はソケットファイルそのものへの書き込みを禁じるだけで、ソケットを通じたAPIの呼び出しは止められないためです。検証でも、:ro でマウントしたソケット経由でDockerネットワークを作成・削除できました。権限を絞りたいなら、Portainerを使うかどうかを含めて、誰に画面を開かせるかで管理します。

Portainer CEをDocker Composeで起動する

イメージのタグは、執筆時点で lts が2.45.1を指していました。自動で版が変わると困る環境では、この記事のように版番号で固定し、更新するときに書き換えます。監視サーバーのLAN側アドレスを例として 192.168.10.5 にしています。

~/stacks/portainer/compose.yaml
services:
  portainer:
    image: portainer/portainer-ce:2.45.1
    command: --http-disabled
    restart: unless-stopped
    ports:
      - "192.168.10.5:9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    secrets:
      - portainer

secrets:
  portainer:
    file: ./portainer.key

volumes:
  portainer_data:
terminal
cd ~/stacks/portainer
head -c 32 /dev/urandom | base64 > portainer.key
chmod 600 portainer.key
docker compose up -d
docker compose logs portainer | grep -E 'starting HTTPS server|setup_token'

イメージが待ち受けるポートは3つあります。9443番がHTTPSの画面、9000番がHTTPの画面、8000番が後述するEdge Agent用のトンネルです。使うのは9443番だけなので、公開するのもそれだけにし、--http-disabled でコンテナ内のHTTPの待ち受けも止めています。このオプションを付けると、起動ログから starting HTTP server | bind_address=:9000 の行が消え、starting HTTPS server だけになります。8000番はEdge Agentを使うときまで公開しません。証明書は初回起動時に自己署名のものが自動で作られ(ログに no cert files found, generating self signed SSL certificates と出ます)、/data/certs/ に保存されます。

secrets の部分は任意ですが、入れておくことをおすすめします。/run/secrets/portainer(起動オプション --secret-key-name で名前を変更可能)に鍵があれば、Portainerはそれを使って設定データベース portainer.db を暗号化します。鍵を渡さずに起動したときはログに proceeding without encryption key と出て、鍵を渡したときはこの行が出なくなることを確認しました。データベースには環境の接続情報やレジストリの認証情報が入るので、ボリュームのバックアップが漏れたときの保険になります。鍵を失うとデータベースを開けなくなるため、portainer.key は別の場所にも保管してください。

初回セットアップ:セットアップトークンと5分の制限

起動したら https://192.168.10.5:9443 を開きます。自己署名証明書なので、ブラウザには警告が出ます。執筆時点の版では、初回の管理者作成にセットアップトークンが必要で、起動時のログに次の形で表示されます(トークンの値は伏せています)。

docker compose logs portainer(抜粋)
setup_token=<64文字の16進数>

Paste it into the setup screen, or send it in the X-Setup-Token header.
Start with --no-setup-token to disable.

画面にトークンを貼り付け、管理者のユーザー名とパスワードを決めます。パスワードは12文字以上が必須で、短いと Password does not meet the requirements で弾かれます。トークンは、起動直後の画面を先に開いた第三者に管理者を作られてしまうのを防ぐ仕組みで、ログを読めるのはホストに入れる人だけ、という前提で成り立っています。

もう1つの安全装置が5分の制限です。起動から5分以内に管理者を作らないと、ログに the Portainer instance timed out for security purposes, to re-enable your Portainer instance, you will need to restart Portainer と出て、以後の作成要求には Administrator initialization timeout が返ります。検証でも起動の5分後にこの状態になり、docker compose restart portainer のあと新しいログのトークンで作成できました。

管理者を作ると、環境(Environment)を追加する画面になります。そのまま進めると、マウントしたソケットを使う local という環境が作られ(接続先は unix:///var/run/docker.sock)、ホームの画面にコンテナ数やボリューム数が表示されます。

最初に見直す設定:一般ユーザーの権限とセッション

家族や同僚に画面を使わせるなら、管理者とは別に一般ユーザー(Standard user)を作り、使ってよい環境だけに割り当てます。CEの一般ユーザーは、割り当てられた環境で自分に許可されたリソースを操作できます。そのうえで、ホストの権限につながる操作を環境ごとの設定で制限できます。2.45.1で local 環境を作った直後の既定値を、APIで読み出した結果が次の表です。

一般ユーザーへの許可(設定の内部名)2.45.1の既定値許可するとできること
バインドマウント(allowBindMountsForRegularUsers)許可しないホストの任意のディレクトリをコンテナに渡す
特権モード(allowPrivilegedModeForRegularUsers)許可しないホストのデバイスやカーネル機能にほぼ無制限に触る
ホストの名前空間(allowHostNamespaceForRegularUsers)許可しないホストのネットワークやプロセスを共有する
デバイスのマッピング(allowDeviceMappingForRegularUsers)許可しない/dev 配下の機器をコンテナに渡す
ケーパビリティ・sysctl・security-opt許可しないカーネルの権限や設定を個別に変える
ボリュームの中身の閲覧(allowVolumeBrowserForRegularUsers)許可しないボリューム内のファイルを画面で見る
スタックの管理(allowStackManagementForRegularUsers)許可するcompose.yamlを書いてサービス一式を動かす

危険な操作は既定で閉じられていますが、スタックだけは一般ユーザーにも開いています。compose.yamlは強力な書式なので、信頼しきれない利用者がいる環境では、環境の設定画面にある「Hide the use of Stacks for non-administrators」もオンにして、スタックの作成を管理者に限るのが無難です。ログの確認と再起動だけを任せたい、という用途ならそれで足ります。

ログインの有効期間は既定で8時間です(設定の UserSessionTimeout が 8h)。共用のPCから使うことがあるなら、設定画面で短くしておきます。

一般ユーザーを作っても、同じ人にホストへのSSHやdockerグループへの所属を許していれば、Portainerの制限は意味がありません。画面側の制限は「その人がPortainer以外の経路でDockerに触れない」ことが前提です。

スタックでcompose.yamlを管理する

スタック(Stacks)は、Composeのプロジェクトを画面から作る機能です。Webエディタに直接書く、ファイルをアップロードする、Gitリポジトリから取り込む、の3つの作り方があり、画面から作ったスタックのcompose.yamlはPortainerのデータボリューム(/data/compose/ の下)に保存されます。環境変数は画面の入力欄で渡せるので、パスワードをcompose.yamlに直書きせずに済みます。

コマンドラインの docker compose up -d で作ったプロジェクトも一覧に表示されますが、画面には This stack was created outside of Portainer. Control over this stack is limited. と出て、compose.yamlの編集や再デプロイはできません。1つのスタックは「CLIとGitで管理する」か「Portainerで管理する」かのどちらかに決め、両方から触らないようにしてください。両方で編集すると、どちらが正しい定義なのか分からなくなります。

Webエディタで書く場合、./config:/config のような相対パスのバインドマウントは、Portainerのデータ領域を基準に解釈されるため、ホスト上で意図した場所を指しません。/srv/stacks/app/config:/config のようにホストの絶対パスで書きます。イメージを新しくするときは、スタックの編集画面で再デプロイする際にイメージの再取得(re-pull)を有効にします。再取得しないと、ローカルに残っている古いイメージのまま作り直されます。

複数のDockerホストを管理する:AgentとEdge Agent

2台目以降のDockerホストは、そのホストでPortainer Agentを動かして登録します。Agentは9001番で待ち受け、Portainerのサーバーがそこへ接続する形です。Agentに届いた命令はそのホストのDockerに対する全権を持つので、9001番に届く相手をPortainerのサーバーだけに絞るファイアウォールの設定を必ず入れます。

サーバー側から届かない場所(別の拠点やNATの内側)にあるホストには、Edge Agentを使います。Edge Agentは逆向きに、ホスト側からPortainerのサーバーの9443番と8000番(トンネル)へ接続してきます。このときに初めて8000番の公開が必要になります。家庭内で数台を管理するだけなら、通常のAgentで十分です。

代替ツールとの使い分け:Dockge・Lazydocker・CLI

コンテナの管理画面はほかにもあり、何を中心に管理したいかで選び分けます。

ツール形得意なこと向く人
Portainer CEWebアプリコンテナ単位の操作、ユーザーごとの権限、複数ホスト家族や同僚にも画面を使わせたい
DockgeWebアプリcompose.yamlをファイルのまま編集・起動するComposeのファイルを主役にしたい
LazydockerターミナルのTUISSH先でコンテナ・ログ・統計を素早く見る自分1人で、ブラウザを開かずに済ませたい
docker CLI+Compose+Gitコマンド変更履歴が残り、再現性が高い構成をコードとして管理したい

1人で運用していて構成をGitで管理しているなら、画面は必須ではありません。画面が欲しくなるのは、コマンドを使わない人に操作を任せたいときと、多数のコンテナの状態を一覧で眺めたいときです。前者ならPortainer、後者ならLazydockerで足りることが多いです。

つまずきポイント

「timed out for security purposes」で先に進めない

起動から5分以内に管理者を作らなかったときの状態です。docker compose restart portainer で再起動し、docker compose logs portainer | grep setup_token で新しいログのトークンを確認してから、5分以内に作成を終えます。

Invalid or missing setup token と言われる

APIや画面にトークンが渡っていません。トークンは管理者がまだいない状態で起動するたびにログへ出力されるので、再起動した場合は最新の行を使います。社内の構築手順などで自動化したい場合は、--setup-token で自分で決めた値を渡すか、--no-setup-token で無効にできますが、後者は起動直後の横取りを防ぐ仕組みを外すことになります。

管理者のパスワードを忘れた

公式の補助イメージでパスワードを再設定できます。コンテナを止めてから、同じデータボリュームをマウントして実行します。検証では Password successfully updated for user: admin に続いて Use the following password to login: と新しいパスワードが表示されました。ボリューム名は docker volume ls で確認します(Composeでは portainer_portainer_data のようにプロジェクト名が前に付きます)。

terminal
docker compose stop portainer
docker run --rm -v portainer_portainer_data:/data portainer/helper-reset-password
docker compose start portainer

ブラウザの証明書警告を消したい

自己署名証明書の警告は、--sslcert と --sslkey で正規の証明書を渡すか、LAN内のリバースプロキシの後ろに置いて消します。Caddyなら reverse_proxy https://portainer:9443 に tls_insecure_skip_verify を付ける形になります(Caddyで自動HTTPSのリバースプロキシを作るガイドを参照)。プロキシがHostヘッダーを書き換える構成では、CSRF対策の検査に引っかかることがあるため、--trusted-origins に画面を開くときのオリジンを指定します。

動作確認

terminal
cd ~/stacks/portainer
docker compose ps
curl -sk https://192.168.10.5:9443/api/system/status
docker volume ls | grep portainer_data

/api/system/status は認証なしで {"Version":"2.45.1","InstanceID":"…"} のようなJSONを返します。版番号が想定どおりで、画面のホームに local 環境が表示され、コンテナ数が docker ps -q | wc -l の結果と一致していれば、Portainerはソケット経由でDockerを正しく読めています。データのバックアップは、コンテナを止めた状態でボリュームを丸ごと固めるのが確実です。

terminal
docker compose stop portainer
docker run --rm -v portainer_portainer_data:/data:ro -v "$PWD":/backup alpine tar czf /backup/portainer-data.tgz -C /data .
docker compose start portainer

よくある質問

Portainerとは何ですか?

コンテナの管理ツールで、DockerやKubernetesのコンテナ、イメージ、ボリューム、スタックをWebブラウザから操作できます。無料のCommunity Editionと、細かい権限管理などを加えた有償のBusiness Editionがあります。ローカルのDockerはソケット経由で、他のホストはAgent経由で管理します。

Portainerは日本語に対応していますか?

執筆時点のCE 2.45.1では対応していません。画面に含まれる言語データは英語だけで、メニューもメッセージも英語で表示されます。操作は画面の構成を覚えれば難しくありませんが、コマンドに不慣れな人に使ってもらう場合は、よく使う操作の手順を画面の英語表記のまま書き残しておくと迷いません。

Dockerの欠点は何ですか?

代表的なのは権限の問題で、Docker Engineはroot権限のデーモンとして動き、そのソケットに書き込める人はホストの全権を持ちます。管理ツールやCIにソケットを渡すと、この権限をそのまま預けることになります。ほかに、コンテナとホストでカーネルを共有するため、仮想マシンほど強い分離ではない点も設計時に考慮が必要です。

KubernetesはDockerを非推奨にしている?

非推奨になったのは、KubernetesがDocker Engineを実行環境として使うための仕組み(dockershim)で、v1.24で削除されました。Dockerで作ったイメージは標準形式なので、containerdなどの実行環境でそのまま動きます。管理画面としては、PortainerがDocker環境とKubernetes環境の両方に対応しています。

まとめ

Portainerの導入自体はcompose.yaml 1つで終わりますが、ソケットを渡した時点で画面の管理者はホストのrootと同じになります。9443番だけをLAN側に公開し、HTTPを止め、データベースを鍵で暗号化し、一般ユーザーにはスタックも含めて必要な操作だけを許す、という順で固めてください。compose.yamlをGitで管理している人は、Portainerを状態確認と日常操作の窓口にとどめると、どちらが正かで迷わずに済みます。

次に読む

$ subscribe --weekly
毎週月曜、企業ITとホームラボの要点を5分で。