
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 にしています。
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: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 を開きます。自己署名証明書なので、ブラウザには警告が出ます。執筆時点の版では、初回の管理者作成にセットアップトークンが必要で、起動時のログに次の形で表示されます(トークンの値は伏せています)。
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 CE | Webアプリ | コンテナ単位の操作、ユーザーごとの権限、複数ホスト | 家族や同僚にも画面を使わせたい |
| Dockge | Webアプリ | compose.yamlをファイルのまま編集・起動する | Composeのファイルを主役にしたい |
| Lazydocker | ターミナルのTUI | SSH先でコンテナ・ログ・統計を素早く見る | 自分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 のようにプロジェクト名が前に付きます)。
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 に画面を開くときのオリジンを指定します。
動作確認
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を正しく読めています。データのバックアップは、コンテナを止めた状態でボリュームを丸ごと固めるのが確実です。
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を状態確認と日常操作の窓口にとどめると、どちらが正かで迷わずに済みます。