Dockerランタイム
Docker実行時にKeeper Secrets Managerからシークレットを取得

機能
Dockerコンテナの実行時にKeeperボルトからシークレットを動的に取得します
前提条件
このページでは、Secrets ManagerとDockerランタイムとの連携について説明します。 この連携を利用するための必要条件は以下のとおりです。
Keeper Secrets Managerへのアクセス(詳細は、クイックスタートガイドをご参照ください)
KeeperアカウントのSecrets Managerアドオンの有効化
Secrets Manager強制ポリシーが有効化されたロールを割り当てられたメンバーシップ
シークレットを共有するKeeper Secrets Managerアプリケーション
アプリケーションの作成手順については、クイックスタートガイドをご参照ください
Keeper Secrets Manager(KSM)CLIツール
KSM CLIの設定手順については、こちらをご参照ください
概説
Keeper Secrets ManagerはDockerランタイムと連携しているため、コンテナの実行時にボルトからシークレットを動的に取得できます。
ksm
コマンドを使用して、コンテナの起動時に環境変数を設定するため、環境変数をデプロイメントスクリプトにハードコーディングする必要はありません。この実装の実際の例を以下に示します。
例:MySQLネットワークユーザーアカウントのプロビジョニング
公式のMySQL dockerを使用すると、ユーザーはMySQL rootパスワードを設定し、環境変数を使用してネットワークアクセス可能なユーザーを作成できます。MySQLインスタンスは、コンテナの実行時にプロビジョニングされます。
公式のMySQL Dockerfileは以下のとおりです。
FROM debian:buster-slim
...
...INSTALL MySQL 8.0 SERVER
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
標準実装では、ENTRYPOINTはコンテナのプロビジョニングを実行し、MYSQLを設定するために渡される環境変数を使用します。参照される環境変数は以下のとおりです。
MYSQL_ROOT_PASSWORD
MYSQL_USER
MYSQL_PASSWORD
MYSQL_DATABASE
以下の手順では、Keeperボルトに格納されたシークレットを使用してMySQLデータベースを初期化する方法を示します。
手順 1: シークレットを格納する2つのボルトの記録を作成します
Secrets Managerアプリケーションによって管理される2つの記録をボルトに作成します。一方の記録にはrootパスワードが含まれます。もう一方の記録には、通常のユーザー、パスワード、およびデータベースの値が含まれます。


ボルトの記録に表示されるUID記録を必ずコピーしてください。これらは、以下の手順3でボルトのシークレットを参照するときに使用します。


手順 2: デフォルトのMySQL dockerfileをベースとしたdockerfileを作成します
Keeper Secrets Manager CLI (ksm
) をインストールし、ksm exec
でENTRYPOINTをラップするdockerfileを作成します
以下のdockerfileでは、Keeper表記法を使用して4つの環境変数が置き換えられています。また、シークレットが格納されているボルトを示すSecrets Managerプロファイルも渡しています。
FROM mysql:debian
ARG BUILD_KSM_INI_CONFIG
ARG BUILD_ROOT_UID
ARG BUILD_USER_UID
RUN apt-get update && \
apt-get install -y python3 python3-pip python3-venv && \
apt-get clean
# 支障を来すおそれのあるシステムインストールモジュールは使用しないようにします。
ENV VIRTUAL_ENV /venv
RUN python3 -m pip install --upgrade pip && \
python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# ディストリビューションに含まれるPythonが古すぎて、新しいモジュールのインストールに支障があるかもしれないため、pipをアップグレードします。
RUN pip3 install --upgrade pip
# Keeper Secrets Manager CLIをインストール
RUN pip3 install keeper-secrets-manager-cli
# 設定をインポートしてデコードし、ksmが検出可能な場所に保存します。
RUN ksm profile import $(printenv --null BUILD_KSM_INI_CONFIG)
ENV MYSQL_ROOT_PASSWORD keeper://${BUILD_ROOT_UID}/field/password
ENV MYSQL_USER keeper://${BUILD_USER_UID}/field/login
ENV MYSQL_PASSWORD keeper://${BUILD_USER_UID}/field/password
ENV MYSQL_DATABASE keeper://${BUILD_USER_UID}/custom_field/database
ENTRYPOINT ["ksm", "exec", "--", "docker-entrypoint.sh"]
手順 3: dockerビルドを実行するシェルスクリプトを作成
docker buildを実行するには、以下のスクリプトでSecrets Managerのデバイス設定と、シークレットを含むボルトのrootユーザーのUID記録とネットワークユーザーのUID記録を渡します。
#!/bin/sh
export CF=$(ksm profile export)
docker build \
--build-arg "BUILD_KSM_INI_CONFIG=${CF}" \
--build-arg "BUILD_ROOT_UID=DvpMcO4xV5nZF6jqLGF1fQ" \
--build-arg "BUILD_USER_UID=VNxZvvNAZ8j2mL4WIjEzjg" \
-t mysql_custom \
.
例:KSM CLI Dockerイメージの使用
KSM CLI Dockerには、GLIBC (ほとんどのLinuxディストリビューション) とMUSL (Alpine Linux) の両方のCLIバイナリへのボリュームマウントが含まれています。ボリュームは、/cli
です。このディレクトリは、docker-composeのvolumes_from
またはコマンドラインdockerの-v
を使用して、別のコンテナにマウントできます。ksmの実行可能ファイルは、Linuxディストリビューションが使用しているCライブラリのバージョン別のディレクトリにあります。
/cli/glibc/ksm
- Ubuntu、Debian、Fedora、CentOSなどの標準GLIBCディストリビューションの場合。/cli/musl/ksm
- Alpine Linuxの場合。
たとえば、CLIバイナリにアクセスする方法を示す簡単なフレームワークを以下に示します。
---
version:"2"
services:
init:
image: keeper/keeper-secrets-manager-cli:latest
main:
image: ubuntu:latest
volumes_from:
- init:ro
command: [ '/cli/glibc/ksm', 'exec', 'printenv', 'MY_LOGIN' ]
environment:
KSM_CONFIG: ewog ...M09IemdQMnc9Igp9
MY_LOGIN: keeper://bf18xLR3aVut5eYy7oIZZZ/field/login
LC_ALL:C.UTF-8
LANG:C.UTF-8
depends_on:
init:
condition: service_completed_successfully
init
サービスは、CLI dockerをロードします。コンテナが起動し、CLIのスプラッシュ画面が表示されてから終了します。コンテナが停止しても、/cli
ボリュームには他のコンテナから引き続きアクセスできます。
main
サービスは、volumes_from
を使用して、CLI dockerのボリュームをディレクトリ/cli
にマウントします。command
でオーバーライドして、KSM CLIのGLIBCバージョンを実行します。command
は、CLIのexec
機能を使用しています。これにより、Keeper表記法を使用する環境変数がシークレット値に置き換えられます。CLIのexec
コマンドは、printenv
アプリケーションを実行しています。これにより、Keeper表記法に設定され、exec
コマンドによって値がシークレットに置き換えられた環境変数MY_LOGINが表示されます。
$ example : docker-compose up
[+] Running 2/0
⠿ Container example-init-1 Created 0.0s
⠿ Container example-main-1 Recreated 0.1s
Attaching to example-init-1, example-main-1
example-init-1 |
example-init-1 | ██╗ ██╗███████╗███╗ ███╗ ██████╗██╗ ██╗
example-init-1 | ██║ ██╔╝██╔════╝████╗ ████║ ██╔════╝██║ ██║
example-init-1 | █████╔╝ ███████╗██╔████╔██║ ██║ ██║ ██║
example-init-1 | ██╔═██╗ ╚════██║██║╚██╔╝██║ ██║ ██║ ██║
example-init-1 | ██║ ██╗███████║██║ ╚═╝ ██║ ╚██████╗███████╗██║
example-init-1 | ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝
example-init-1 |
example-init-1 | Current Version:1.0.13
example-init-1 |
example-init-1 | Running in shell mode.Type 'quit' to exit.
example-init-1 |
example-init-1 exited with code 0
example-main-1 | john.smith@localhost
example-main-1 exited with code 0
例: KSM CLI Dockerと他のベンダーのDockerイメージの併用
上記の例と同様に、カスタムDockerイメージを作成せずに、KSM CLI dockerを使用して、別のベンダーのDockerイメージのエントリポイントとコマンドをオーバーライドできます。
この例では、最初の2つの例を組み合わせます。
この例では、DockerイメージがDocker Hubリポジトリから切り離されて、イメージのDockerfileがGitHubに格納されていることを前提としています。
オペレーティングシステムのディストリビューション
最初の手順は、ベンダーのDockerイメージがどのオペレーティングシステムのディストリビューションに基づいて作成されているかを判定することです。通常はタグ名で判定できます。たとえば、名前のイメージタグ名に「alpine」が含まれている場合は、Alpine Linuxディストリビューションであることがわかります。
イメージタグ名にディストリビューションが示されていない場合は、そのイメージのDocker Hubウェブページで、「サポートされているタグ (Supported tags)」セクションのタグ名をクリックします。すると、Dockerfileの内容が表示されます。FROMステートメントは、ベンダーがイメージ作成のベースにしたディストリビューションを示します。FROMステートメントで判明しない場合は、継承したFROMイメージのDockerfileをご確認ください。

MySQL 8.0.31は、タグ名にオペレーティングシステムのディストリビューションを示しません。MySQL Docker Hubページでは、8.0.31タグがGitHubリポジトリにリンクしています。このDockerfileから、ディストリビューションがOracle Linuxであることがわかります。

ディストリビューションをチェックする目的は、どのバージョンのlibcライブラリが使用されているかを確認することです。ほとんどのディストリビューションはGLIBCを使用していますが、一部 (主にAlpine Linux) はMUSLを使用しています。これは、KSM CLI Dockerイメージから正しいバイナリを選択するために必要です。間違ったバイナリを選択すると、exec /cli/musl/ksm: no such file or directory
またはexec /cli/glibc/ksm: no such file or directory
のようなエラーが表示されます。この例では、Oracle LinuxはGLIBCディストリビューションです。
エントリーポイントとコマンド
次の手順では、ベンダーのDockerイメージのENTRYPOINTとCMDを指定します。Dockerfileには、ENTRYPOINTとCMDの両方、またはいずれか一方が記載されます。

このMySQL Dockerfileでは、ENTRYPOINTは["docker-entrypoint.sh"]
で、CMDは["mysqld"]
です。つまり、ENTRYPOINTはCMDの先頭に追加されるため、コンテナの起動時にdocker-entrypoint.sh mysqld
が実行されます。
docker-compose.yml
docker-compose.yml
docker-composeは2つのサービスを使用します。
initサービスは、keeper/keeper-secrets-manager-cli
Dockerイメージボリュームをロードします。このイメージは起動して終了しますが、終了後もボリュームには引き続きアクセスできます。
mainサービスは、initサービスの後に実行されます。これは、docker-composeのdepends_on
ディレクティブを使用して実行します。このサービスには、KSM CLI exec
コマンドによって置き換えられる、表記法を使用した環境変数が含まれており、KSM CLIに必要なBase64でエンコードされた設定も含まれています。MYSQL_環境変数は、データベースをプロビジョニングするためにMySQL Dockerイメージによって使用されます。
また、mainサービスはvolumes_from
を使用して、initサービスからボリュームをマウントします。KSM CLI Dockerイメージには、ボリュームをエクスポートして、mainサービスコンテナにマウントされる場所が定義されています。バイナリは/cli
(libcバージョンとksm
バイナリ名が続きます)にマウントされます。
version:'3.0'
services:
init:
image: keeper/keeper-secrets-manager-cli:latest
main:
image: mysql:8.0
environment:
KSM_CONFIG: "ewog ....RQ3pQMnc9Igp9"
MYSQL_USER: "keeper://KOJLz4Wzbqfi9xUO-VMViA/field/login"
MYSQL_PASSWORD: "keeper://KOJLz4Wzbqfi9xUO-VMViA/field/password"
MYSQL_ROOT_PASSWORD: "keeper://KOJLz4Wzbqfi9xUO-VMViA/custom_field/Root Password"
MYSQL_DATABASE: "keeper://KOJLz4Wzbqfi9xUO-VMViA/custom_field/Database"
depends_on:
init:
condition: service_completed_successfully
entrypoint: ["/cli/glibc/ksm", "exec", "docker-entrypoint.sh"]
command: ["mysqld"]
ports:
- "3306:3306"
volumes_from:
- init:ro
MySQLイメージはOracleディストリビューション (GLIBCディストリビューション) を使用するため、mainサービスは/cli/glibc/ksm
バイナリを使用します。
mainサービスは、MySQLイメージのENTRYPOINTとCMDをオーバーライドします。これは、entrypointとcommandを使用して実行します。エントリポイントは、KSM CLIのexec
コマンドを使用して、元のENTRYPOINT docker-entrypoint.sh
を実行します。commandは同じですが、docker-compose.yml
で設定する必要があります。設定しないと、サービスは単に終了します。
使用しているDockerイメージによっては、ENTRYPOINTとCMDのいずれか一方、またはその両方のオーバーライドが必要になる場合があります。
結果
サービスが起動されると、initサービスが最初に実行され、コード0で終了します。これは、正常終了したことを意味します。その後、mainサービスが起動し、KSM CLIのexec
コマンドを実行してから、mysqld
によってdocker-entrypoint.sh
が実行されます。この時点で、環境変数はシークレットに置き換えられ、MySQLがプロビジョニングされ、mysqld
が動作しています。
$ my_mysql : docker-compose up
[+] Running 3/3
⠿ Network my_mysql_default Created 0.0s
⠿ Container my_mysql-init-1 Created 0.1s
⠿ Container my_mysql-main-1 Created 0.0s
Attaching to my_mysql-init-1, my_mysql-main-1
my_mysql-init-1 |
my_mysql-init-1 | ██╗ ██╗███████╗███╗ ███╗ ██████╗██╗ ██╗
my_mysql-init-1 | ██║ ██╔╝██╔════╝████╗ ████║ ██╔════╝██║ ██║
my_mysql-init-1 | █████╔╝ ███████╗██╔████╔██║ ██║ ██║ ██║
my_mysql-init-1 | ██╔═██╗ ╚════██║██║╚██╔╝██║ ██║ ██║ ██║
my_mysql-init-1 | ██║ ██╗███████║██║ ╚═╝ ██║ ╚██████╗███████╗██║
my_mysql-init-1 | ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝
my_mysql-init-1 |
my_mysql-init-1 | Current Version:1.0.14
my_mysql-init-1 |
my_mysql-init-1 | Running in shell mode.Type 'quit' to exit.
my_mysql-init-1 |
my_mysql-init-1 exited with code 0
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]:Entrypoint script for MySQL Server 8.0.31-1.el8 started.
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]:Switching to dedicated user 'mysql'
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]:Entrypoint script for MySQL Server 8.0.31-1.el8 started.
my_mysql-main-1 | 2022-10-31 21:35:26+00:00 [Note] [Entrypoint]:Initializing database files
my_mysql-main-1 | 2022-10-31T21:35:26.830527Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release.Please use SET GLOBAL host_cache_size=0 instead.
my_mysql-main-1 | 2022-10-31T21:35:26.830594Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.31) initializing of server in progress as process 83
...
my_mysql-main-1 | 2022-10-31T21:35:35.611063Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections.Version:'8.0.31' socket: '/var/run/mysqld/mysqld.sock' port:3306 MySQL Community Server - GPL.
my_mysql-main-1 | 2022-10-31T21:35:35.611015Z 0 [System] [MY-011323] [Server] X Plugin ready for connections.Bind-address: '::' port:33060, socket: /var/run/mysqld/mysqlx.sock
Dockerランタイムの例に貢献
このページに貢献できる素晴らしい例をお持ちであれば、Slackでメッセージを送信するか、またはメールでお知らせくださいsm@keepersecurity.com。
最終更新