以前、Docker コンテナの起動後にボリュームをマウントできるかどうか尋ねられたことがあります。mnt 名前空間の動作を考えると、最初はこれを実現するのは難しいだろうと思いました。しかし、今ではそれが達成されたと思います。
最初の手順で作成した一時マウント ポイントをアンマウントします。 予防 次の例では、入力する必要がある内容とマシンの応答を区別できるように、これがシェル コマンド ライン プロンプトであることを示すために、意図的に $ 記号を含めています。一部の複数行コマンドでは、引き続き > を使用します。これにより、例のコマンドを簡単にコピーして貼り付けることができなくなることに気付きました。コードをコピーして貼り付ける場合は、記事の最後にあるサンプル スクリプトを確認してください。 詳細な手順 次の例では、次のコマンドを使用して charlie という名前の単純なコンテナを起動したことを前提としています。 $ docker run --name charlie -ti ubuntu bash 必要なのは、ホスト フォルダー センター まず、nsenter と docker-enter ヘルパー スクリプトが必要です。なぜ?コンテナからファイルシステムをマウントしたいからです。セキュリティ上の理由により、コンテナではこれを行うことはできません。 nsenter を使用すると、上記のセキュリティ制限を突破し、コンテナのコンテキスト (厳密には名前空間) 内で任意のコマンドを実行できます。もちろん、これには Docker ホスト上のルート権限が必要です。 nsenter をインストールする最も簡単な方法は、docker-enter スクリプトと組み合わせて実行することです。 $ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter 詳細については、nsenter プロジェクトのホームページを参照してください。 ファイルシステムを見つける ホストフォルダ (/home/jpetazzo/Work/DOCKER/docker) を含むファイルシステムをコンテナにマウントします。次に、どのファイル システムにこのディレクトリが含まれているかを調べる必要があります。 まず、ファイルがシンボリック リンクである場合、またはそのパスにシンボリック リンクが含まれている場合は、ファイルを正規化 (または逆参照) する必要があります。 $ readlink --canonicalize /home/jpetazzo/Work/DOCKER/docker github.com の docker ディレクトリに docker というファイルを作成します。 はは、確かにシンボリックリンクですね!これを環境変数に設定してみましょう: $ HOSTPATH=/home/jpetazzo/Work/DOCKER/docker $REALPATH=$(readlink --canonicalize $HOSTPATH) 次に、どのファイルシステムにこのパスが含まれているかを調べる必要があります。私たちは、やや意外なツールである df を使用してこれを行います。 $ df $リアルパス ファイルシステム 1Kブロック 使用済み 使用可能 使用率 マウント済み /sda2 245115308 156692700 86157700 65% /home/jpetazzo -P フラグを使用します (Solaris または BSD に Docker をインストールするときに、特殊な df または他の人の df がある場合に備えて、POSIX 形式を強制します)。また、結果も変数に格納します。 $ FILESYS=$(df -P $REALPATH | tail -n 1 | awk '{print $6}') ファイルシステムのデバイス(およびサブルート)を見つける 現在、システムにはバインド マウントや BTRFS サブボリュームは存在しないため、/proc/mounts を調べて、/home/jpetazzo ファイル システムに対応するデバイスを見つける必要があります。しかし、私のシステムでは、/home/jpetazzo は BTRFS プールのサブボリュームです。サブボリューム情報 (またはバインド マウント情報) を取得するには、/proc/self/moutinfo を確認する必要があります。 mountinfo について聞いたことがない場合は、proc.txt のカーネルドキュメントを確認してください。 まず、ファイル システム デバイス情報を取得します。 $ 読み取り中 DEV マウント ジャンク > [ $MOUNT = $FILESYS ] を実行する && break > 完了 </proc/mounts $ エコー $DEV /dev/sda2 次に、サブルート情報 (マウントされたファイル システムへのパス) を取得します。 $ ABC SUBROOT MOUNT JUNK を読み取り中 > [ $MOUNT = $FILESYS ] を実行する && break > 完了 < /proc/self/mountinfo $ echo $サブルート /jpetazzo とても良い。これで、 $ SUBPATH=$(echo $REALPATH | sed s,^$FILESYS,,) 注意: この方法は、パスに「,」が含まれていない場合にのみ機能します。パスに「,」があり、この記事の方法でディレクトリをマウントしたい場合は、お知らせください。 (この問題を解決するには、シェル トライアドを呼び出す必要があります: ジェシー、ソウルシェイク、ティアノン?) コンテナに入る前に最後に行うことは、ブロック デバイスのメジャー番号とマイナー番号を見つけることです。 stat を使用できます: $ stat --format "%t %T" $DEV 8 2 これら 2 つの数値は 16 進数であることに注意してください。後で 2 進数が必要になります。これは次のように変換できます。 $ DEVDEC=$(printf "%d %d" $(stat --format "0x%t 0x%T" $DEV)) 要約する 最後にもう1つのステップがあります。説明できない理由で、一部のファイルシステム (BTRFS を含む) は、複数回マウントされた後に /proc/mounts のデバイス フィールドを更新します。つまり、コンテナ内に /tmpblkdev という一時ブロック デバイスを作成し、それを使用して独自のファイルシステムをマウントすると、ファイルシステムは (ホスト マシン上で!) /dev/sda2 ではなく /tmpblkdev として表示されます。これは無害に思えるかもしれませんが、実際には、ファイル システム ブロック デバイスを取得しようとする後続の試行が失敗する原因になります。 簡単に言うと、コンテナ内のブロック デバイス ノードがホスト マシンと同じパスに配置されていることを確認する必要があります。 次の操作を行う必要があります: $ docker-enter charlie --sh -c \ > "[ -b $DEV ] || mknod --mode 0600 $DEV b $DEVDEC" ファイル システムをマウントするための一時マウント ポイントを作成します。 $ docker-enter charlie --mkdir /tmpmnt $ docker-enter charlie --mount $DEV /tmpmnt ボリューム マウント ポイントが存在することを確認し、ボリュームをバインド マウントします。 $ docker-enter charlie --mkdir -p /src $ docker-enter charlie --mount -o bind /tmpmnt/$SUBROOT/$SUBPATH /src 一時マウントポイントを削除します。 $ docker-enter charlie --umount /tmpmnt $ docker-enter charlie --rmdir /tmpmnt (デバイス ノードはクリアしません。そもそもデバイスが存在するかどうかを確認するのは冗長かもしれませんが、すでに十分複雑です。) ミッション完了! すべてを自動化 次の段落はそのままコピーして貼り付けることができます。 #!/bin/sh セット-e コンテナ=チャーリー HOSTPATH=/home/jpetazzo/Work/DOCKER/docker CONTPATH=/src REALPATH=$(readlink --canonicalize $HOSTPATH) FILESYS=$(df -P $REALPATH | tail -n 1 | awk '{print $6}') DEV MOUNT JUNKを読みながら [ $MOUNT = $FILESYS ] を実行し、break する 完了 </proc/mounts [ $MOUNT = $FILESYS ] # 正常性チェック! \ABC SUBROOT MOUNT JUNKを読みながら \do [ $MOUNT = $FILESYS ] && break \done < /proc/self/mountinfo [ $MOUNT = $FILESYS ] # マウントの健全性チェック! SUBPATH=$(echo $REALPATH | sed s,^$FILESYS,,) DEVDEC=$(printf "%d %d" $(stat --format "0x%t 0x%T" $DEV)) docker-enter $コンテナ --sh -c \ "[ -b $DEV ] || mknod --mode 0600 $DEV b $DEVDEC" docker-enter $コンテナ --mkdir /tmpmnt docker-enter $CONTAINER --mount $DEV /tmpmnt docker-enter $コンテナ --mkdir -p $CONTPATH docker-enter $CONTAINER --mount -o bind /tmpmnt/$SUBROOT/$SUBPATH $CONTPATH docker-enter $コンテナ --umount /tmpmnt docker-enter $コンテナ --rmdir /tmpmnt ステータスと制限 上記の方法は、ブロック デバイスをベースとしないファイル システムには適用されません。/proc/mounts がブロック デバイス ノードを正しく取得できる場合にのみ機能します (前述のように、常に正しく取得できるとは限りません)。また、私はこれをクラウド インスタンスなどではなく、自分の環境でのみテストしましたが、そこでも当てはまるかどうか興味があります。 以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
1. クエリを最適化するには、テーブル全体のスキャンを避けてください。まず、where と orde...
参考までに、Vue3でナビゲーションバーコンポーネントをカプセル化し、スクロールバーのスクロールに合...
エフェクトのスクリーンショット:実装コード:コードをコピーコードは次のとおりです。 <!DOC...
この記事では、ポップアップボックスコンポーネントメッセージのVue3手動カプセル化の具体的なコードを...
この記事では、以下の環境をテストします。 CentOS 7 64 ビット 最小 MySQL 5.7 ...
最近、携帯電話で https が有効になりました。緑色のロックを取得するには、次の問題を解決する必要...
目次1. クロージャを使用する2. ES6クラスを使用する3. ES2020提案を使用する4. We...
目次1. 配列の分解2. オブジェクトの分解3. 不完全な解体4. 分割代入を使用して変数交換を実装...
目次1. ファイアウォールの現在の状態を確認する2. ファイアウォールサービスを開始する3. ファイ...
導入MySQL データベースを使用する場合、int を主キーとして使用し、自動インクリメントに設定す...
MySQL v5.7.19 正式版(32/64 ビットインストール版および zip 解凍版) 1. ...
Chrome ブラウザで Web ページを開くと、ページを右クリックすると 2 つの非常によく似たオ...
ラジオ ボタンや複数選択ボタンにスタイルを追加する方法や、ボタンを大きくする方法を尋ねる人を以前見か...
問題を見つける最近、仕事で問題が発生しました。MySQL データベースにテーブルを作成するときに、ラ...
通常の説明%はどのクライアントでも接続できることを意味しますlocalhostはローカルコンピュータ...