Dockerボリューム権限管理の詳細な説明

Dockerボリューム権限管理の詳細な説明

ボリュームデータボリュームは Docker の重要な概念です。データ ボリュームは、1 つ以上のコンテナーで使用できる特別なディレクトリであり、コンテナー アプリケーションのストレージに貴重な機能を提供します。

  • 永続データはコンテナのライフサイクルから切り離されており、コンテナが削除された後もデータ ボリューム内のコンテンツを保持できます。 Docker 1.9 以降に導入された名前付きボリュームを使用すると、データ ボリュームのライフ サイクルをより便利に管理できます。データ ボリュームは個別に作成および削除できます。
  • データボリュームはコンテナ間でデータを共有するために使用できます
  • さまざまなタイプのデータストレージ実装をサポートできます

Docker はデフォルトでホスト上のローカル ファイル ボリュームをサポートし、ホストのディレクトリをコンテナーにマウントできます。コンテナ階層化ファイルシステムによってパフォーマンスが低下することはないため、ローカル ファイル ボリュームは、MySQL データベース ファイルの保存など、高パフォーマンスのデータ アクセスを必要とするシナリオに非常に適しています。同時に、Docker はボリューム プラグインを通じてさまざまな種類のデータ ボリュームをサポートしており、さまざまなアプリケーション負荷のストレージ要件をより柔軟に解決できます。たとえば、Alibaba Cloud Container Service は、クラウド ディスク ベースのブロック ストレージと OSSFS および NAS/NFS ベースの共有ファイル ストレージを備えたコンテナーを提供できます。

ただし、Docker ボリュームの権限の管理は非常にわかりにくいことがよくあります。この記事では、Docker データ ボリュームの権限管理における一般的な問題と解決策を例を挙げて紹介します。

Jenkinsからローカルデータボリュームをマウントする際のエラーについて

同僚が最近、コンテナ内で Jenkins を実行する際に問題に遭遇しました。再現手順は次のとおりです。

注意: Windows/Mac を使用している場合は Boot2docker 仮想マシンにログインする必要がありますが、Linux の場合は必要ありません。

docker-machine ssh デフォルト

Jenkinsの公式イメージを起動してログを確認する

docker run -d -p 8080:8080 -p 50000:50000 --name ジェンキンス ジェンキンス
docker ログ ジェンキンス

「jenkins」コンテナのログを見ると、すべてが正常であることが分かります。

ただし、Jenkins 構成データを永続化するために、ホストの現在のディレクトリにあるデータ フォルダーをコンテナー内のディレクトリ "/var/jenkins_home" にマウントすると、問題が発生します。

docker rm -f ジェンキンス
docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home --name jenkins jenkins
docker ログ ジェンキンス

エラーログは次のとおりです

touch: '/var/jenkins_home/copy_reference_file.log' にアクセスできません: 権限が拒否されました
/var/jenkins_home/copy_reference_file.log に書き込めません。ボリュームの権限が間違っていますか?

何が起こっているのか?

前の起動方法で「/var/jenkins_home」ディレクトリの権限を確認し、Jenkinsコンテナの現在のユーザーを確認しましょう。現在のユーザーは「jenkins」であり、「/var/jenkins_home」ディレクトリはjenkinsユーザーが所有しています。

docker@default:~$ docker run -ti --rm --entrypoint="/bin/bash" jenkins -c "whoami && id"
ジェンキンス
uid=1000(jenkins) gid=1000(jenkins) グループ=1000(jenkins)

docker@default:~$ docker run -ti --rm --entrypoint="/bin/bash" jenkins -c "ls -la /var/jenkins_home"
合計 20
drwxr-xr-x 2 jenkins jenkins 4096 6月 5日 08:39 .
drwxr-xr-x 28 root root 4096 5月24日 16:43 ..
-rw-r--r-- 1 jenkins jenkins 220 2014年11月12日 .bash_logout
-rw-r--r-- 1 jenkins jenkins 3515 2014年11月12日 .bashrc
-rw-r--r-- 1 ジェンキンス ジェンキンス 675 2014年11月12日 .profile

ローカルデータボリュームをマッピングする場合、/var/jenkins_homeディレクトリの所有者はrootユーザーになります。

docker run -ti --rm -v $(pwd)/data:/var/jenkins_home --entrypoint="/bin/bash" jenkins -c "ls -la /var/jenkins_home"
合計 4
drwxr-sr-x 2 ルートスタッフ 40 6月 5日 08:32 .
drwxr-xr-x 28 root root 4096 5月24日 16:43 ..

これにより、「jenkins」ユーザーのプロセスが「/var/jenkins_home」ディレクトリにアクセスすると、アクセス許可が拒否される問題が発生する理由が説明されます。

ホストマシン上のデータボリュームディレクトリを再度確認してみましょう。現在のパスの下にある「data」ディレクトリの所有者は「root」です。これは、このディレクトリがDockerプロセスによってデフォルトで作成されるためです。

docker@default:~$ ls -laデータ
合計 0
drwxr-sr-x 2 ルートスタッフ 40 6月 5 08:32 ./
drwxr-sr-x 5 docker スタッフ 160 6月 5日 08:32 ../

問題を発見した後の対応する解決策も非常に簡単です。現在のディレクトリの所有者を uid 1000 に割り当ててから、「jenkins」コンテナを起動すると、すべて正常になります。

sudo chown -R 1000データ
docker ジェンキンスを起動する

このとき、ブラウザを使用して「http://192.168.99.100:8080/」にアクセスし、Jenkins Web インターフェースを表示します。注: アクセスできない場合は、docker-machine ip コマンドを使用して現在の Docker ホストの IP アドレスを取得する必要がある場合があります。

再びコンテナに入り、「/var/jenkins_home」ディレクトリの権限を確認すると、その所有者は「jenkins」になっています。

docker@default:~$ docker exec jenkins ls -la /var/jenkins_home
合計 24
drwxr-sr-x 11 jenkins スタッフ 340 6月 5日 09:00 .
drwxr-xr-x 28 root root 4096 5月24日 16:43 ..
drwxr-sr-x 3 jenkins スタッフ 60 6月 5 08:59 .java
-rw-r--r-- 1 jenkins スタッフ 289 6月 5日 08:59 copy_reference_file.log
...

興味深いのは、ホスト上で確認できる「data」ディレクトリの所有者が「docker」であることです。これは、「boot2docker」ホスト上の「docker」ユーザーの uid も「1000」であるためです。

docker@default:~$ ls -laデータ
合計 20
drwxr-sr-x 2 docker スタッフ 40 6月 5日 11:55 ./
drwxr-sr-x 6 docker スタッフ 180 6月 5日 11:55 ../
...

この時点で、コンテナのローカル データ ボリューム内のファイル/ディレクトリの権限は、uid/gid が Docker コンテナとホスト内の異なるユーザー名/グループ名にマップされる可能性があることを除いて、ホスト上の権限と一致していることが既にわかっています。

上記では、ホスト マシンで chown コマンドを実行するときに、特定のユーザー名ではなく uid を使用するという一般的なトリックを使用して、正しい所有者を設定できるようにしました。

問題は解決したが、考えることはまだ終わっていない。ローカル データ ボリュームを使用する場合、Jenkins コンテナーはホスト ディレクトリのアクセス許可の正確性に依存するため、自動展開に余分な作業が追加されます。 Jenkins コンテナにデータ ボリュームの正しいアクセス許可を自動的に設定させる方法はありますか?この問題は、非ルート モードで実行される多くのアプリケーションにも当てはまります。

非ルートアプリケーションのローカルデータボリュームを正しくマウントする

万能の stackoverflow.com には、関連する多くの議論が掲載されています。最も有益な質問と回答の 1 つは次のとおりです。

http://stackoverflow.com/questions/23544282/docker 共有ボリュームの権限を管理する最良の方法は何ですか?

基本的な考え方は 2 つあります。

1 つは、データ コンテナー方式を使用してコンテナー間でデータ ボリュームを共有することです。これにより、ホスト マシン上のデータ ボリュームのアクセス許可の問題を解決する必要がなくなります。 Docker はバージョン 1.9 以降、純粋なデータ コンテナーを置き換える名前付きボリュームを提供しているため、この問題を実際に解決する必要があります。

もう 1 つのアイデアは、コンテナを root ユーザーとして起動し、コンテナ起動スクリプトで「chown」コマンドを使用してデータ ボリューム ファイルのアクセス許可を変更してから、非 root ユーザーに切り替えてプログラムを実行することです。

この問題を解決するために、2 番目のアイデアを参考にしましょう。

以下は、Jenkins イメージに基づく Dockerfile です。「root」ユーザーに切り替えて、イメージに「gosu」コマンドと新しいエントリ ポイント「/entrypoint.sh」を追加します。

jenkins:latestより
ユーザー ルート
GOSU_SHA=5ec5d23079e94aea5f7ed92ee8a1a34bbf64c2d4053dadf383992908a2f9dc8a を実行してください \
 && curl -sSL -o /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.9/gosu-$(dpkg --print-architecture)" \
 && chmod +x /usr/local/bin/gosu \
 && echo "$GOSU_SHA /usr/local/bin/gosu" | sha256sum -c - 
コピー entrypoint.sh /entrypoint.sh
エントリポイント ["/entrypoint.sh"]

注: gosu は、公式の Docker イメージによく登場する小さなツールです。これは、「su」コマンドと「sudo」コマンドの軽量な代替品であり、tty とシグナル配信に関するいくつかの問題を解決します。

新しいエントリ ポイント「entrypoint.sh」の内容は次のとおりです。「JENKINS_HOME」ディレクトリの所有権を「jenkins」に設定し、「gosu」コマンドを使用して「jenkins」ユーザーに切り替えて「jenkins」アプリケーションを実行します。

#!/bin/bash
セット-e
chown -R 1000 "$JENKINS_HOME"
gosu jenkins /bin/tini -- /usr/local/bin/jenkins.sh を実行します

https://github.com/denverdino/docker-jenkins から関連コードを直接取得し、独自の Jenkins イメージを構築できます。実行コマンドは次のとおりです。

git クローン https://github.com/AliyunContainerService/docker-jenkins
jenkins のディレクトリに移動します。
denverdino/jenkins を実行します。

次に、新しいイメージに基づいてJenkinsコンテナを起動します。

docker rm -f ジェンキンス
docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home --name jenkins denverdino/jenkins

要約する

この記事では、Docker データ ボリュームの基本的な概念について説明します。非ルート プロセスがローカル データ ボリュームにアクセスするときに発生するアクセス許可の問題に対する解決策を提供しました。今後も Docker データ ボリュームで発生するその他の問題についてまとめていく予定です。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Docker 学習に関する簡単な説明: Docker データ量 (ボリューム)
  • Dockerデータ管理の名前付きボリュームの詳細な説明
  • Docker におけるコンテナデータボリュームとデータ管理の詳細な説明
  • Dockerfile命令VOLUMEの簡単な紹介
  • Docker ボリュームの使用の詳細と例

<<:  JavaScript で H5 ゴールド コイン関数を実装する (サンプル コード)

>>:  忘れられたMySQLパスワードとログインエラーの問題について簡単に説明します

推薦する

Linux における mv コマンドの高度な使用例

序文mv コマンドは、move の略語で、ファイルを移動したり、ファイル名を変更したり (ファイルの...

MySQLでビューを作成する方法

基本的な構文CREATE VIEW ステートメントを使用してビューを作成できます。構文の形式は次のと...

VueでJSXを使用する方法

JSXとは何かJSX は Javascript の構文拡張であり、JSX = Javascript ...

HTML で入力プロンプトのテキスト スタイルを変更するためのサンプル コード

多くのウェブサイトでは、入力ボックスにヒントテキストが表示されています。入力ボックスにヒントテキスト...

MySQL テーブルを返すとインデックスが無効になるケースの説明

導入MySQL InnoDB エンジンがレコードをクエリし、インデックス カバレッジを使用できない場...

HTML 9グリッドレイアウトの実装方法

ウェブサイトのレイアウトの多様化は、当社のフロントエンドの得意分野です。最近、UC ブラウザのデフォ...

美しいチェックボックススタイル(複数選択ボックス)はIE8/9/10、FFなどと完全に互換性があります。

恥ずかしながら、このようなよく使われるチェックボックスのスタイルを変更するために、Baidu で長い...

データベースSQL文の最適化

最適化する理由:実際のプロジェクトが開始され、データベースが一定期間稼働した後、初期のデータベース設...

JavaScript ベースのパスワード ボックス検証情報の実装

この記事では、パスワードボックスの検証情報を実装するためのJavaScriptの具体的なコードを例と...

MySQL でパーティション分割後にクエリを実装するために MRG_MyISAM (MERGE) を使用する例

大量のデータベース データを最適化することは非常に高度な科学であり、開発者が習得する必要がある専門的...

MySQL の暗号化と復号化の例

MySQL の暗号化と復号化の例データの暗号化と復号化はセキュリティ分野で非常に重要です。プログラマ...

HTML テーブル マウス ドラッグ ソート機能

効果画像: 1. ファイルをインポートする<script src="js/jquer...

Dockerが新しいイメージをロードした後にリポジトリとタグ名が両方ともnoneになる問題を解決する

次のコマンドを使用できます: docker tag [イメージID] [名前]:[バージョン]例えば...

Angularが予期しない例外エラーを処理する方法の詳細な説明

前面に書かれたコードがどれだけ適切に記述されていても、すべての可能性のある例外を完全に処理することは...

Vueのprovideとinjectの使い方と原則を分析する

まず、provide/inject を使用する理由について説明しましょう。祖父コンポーネントと孫コン...