# Dockerランタイム

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FIXjoFUijB6N9qawVGkjX%2Fimage.png?alt=media&#x26;token=f66226f4-977b-49d6-b6da-dc390bed2031" alt=""><figcaption></figcaption></figure>

## 機能

* Dockerコンテナの実行時にKeeperボルトからシークレットを動的に取得します

{% hint style="info" %}
Keeper Secrets Manager機能の完全なリストについては、[概要](https://docs.keeper.io/jp/keeperpam/secrets-manager/overview)をご参照ください。
{% endhint %}

## 前提条件

このページでは、Secrets ManagerとDockerランタイムとの連携について説明します。 この連携を利用するための必要条件は以下のとおりです。

* Keeper Secrets Managerへのアクセス（詳細は、[クイックスタートガイド](https://docs.keeper.io/jp/keeperpam/secrets-manager/quick-start-guide)をご参照ください）
  * KeeperアカウントのSecrets Managerアドオンの有効化
  * Secrets Manager強制ポリシーが有効化されたロールを割り当てられたメンバーシップ
* シークレットを共有するKeeper [Secrets Managerアプリケーション](https://github.com/Keeper-Security/gitbook-jp-secrets-manager/blob/main/about/terminology/README.md#application)
  * アプリケーションの作成手順については、[クイックスタートガイド](https://github.com/Keeper-Security/gitbook-jp-secrets-manager/blob/main/quick-start-guide/README.md#create-a-secrets-manager-application)をご参照ください
* [ワンタイムアクセストークン](https://docs.keeper.io/jp/keeperpam/secrets-manager/about/one-time-token)
* [Keeper Secrets Manager（KSM）CLIツール](https://docs.keeper.io/keeperpam/secrets-manager/secrets-manager-command-line-interface)
  * KSM CLIの設定手順については、[こちら](https://github.com/Keeper-Security/gitbook-jp-secrets-manager/blob/main/secrets-manager-command-line-interface/README.md#rkarukuraiantodebaisuno)をご参照ください

## 概説

Keeper Secrets ManagerはDockerランタイムと連携しているため、コンテナの実行時にボルトからシークレットを動的に取得できます。

**`ksm`**&#x30B3;マンドを使用して、コンテナの起動時に環境変数を設定するため、環境変数をデプロイメントスクリプトにハードコーディングする必要はありません。この実装の実際の例を以下に示します。

## 例:MySQLネットワークユーザーアカウントのプロビジョニング

公式の[MySQL docker](https://hub.docker.com/_/mysql/)を使用すると、ユーザーは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パスワードが含まれます。もう一方の記録には、通常のユーザー、パスワード、およびデータベースの値が含まれます。

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FEgF49Y4bqrKa9r84IsOm%2Fimage.png?alt=media&#x26;token=296a20ef-7477-4598-8d3a-6d7f61e54fa3" alt=""><figcaption><p>MySQL DBのroot</p></figcaption></figure>

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FFHJGoxvQDTK3FAwknXGs%2Fimage.png?alt=media&#x26;token=bca08a49-612a-4a1d-919c-385c3c353306" alt=""><figcaption><p>MySQL DBのユーザー</p></figcaption></figure>

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

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FREFWNtF31mW55uarY3fh%2Fimage.png?alt=media&#x26;token=a59c8d19-44b2-4640-8d1e-8f211d294eb6" alt=""><figcaption><p>rootの記録のUID記録を取得</p></figcaption></figure>

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FTEnmZWpc5t9DG860CoY4%2Fimage.png?alt=media&#x26;token=966cc3ac-d4b0-4fc8-a141-ef17377f4091" alt=""><figcaption><p>ユーザーの記録のUID記録を取得</p></figcaption></figure>

**手順 2: デフォルトのMySQL dockerfileをベースとしたdockerfileを作成します**

Keeper Secrets Manager CLI (**`ksm`**) をインストールし、**`ksm exec`**&#x3067;ENTRYPOINTをラップするdockerfileを作成します

以下のdockerfileでは、[Keeper表記法](https://docs.keeper.io/jp/keeperpam/secrets-manager/about/keeper-notation)を使用して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記録を渡します。

```bash
#!/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](https://docs.keeper.io/jp/keeperpam/secrets-manager/secrets-manager-command-line-interface/docker-container)には、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表記法](https://docs.keeper.io/jp/keeperpam/secrets-manager/about/keeper-notation)を使用する環境変数がシークレット値に置き換えられます。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をご確認ください。

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FnxW1jBeinHSbll3p8FWk%2Fimage.png?alt=media&#x26;token=6066d525-5a05-4fe4-8964-879e367beb65" alt=""><figcaption></figcaption></figure>

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

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FEXevUMYh60KGFyIuTq9i%2Fimage.png?alt=media&#x26;token=f30f26b2-582a-4447-89a8-1db08ab50081" alt=""><figcaption></figcaption></figure>

ディストリビューションをチェックする目的は、どのバージョンの**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**の両方、またはいずれか一方が記載されます。

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FJqJEuSJMe14JIFoUMF4u%2Fimage.png?alt=media&#x26;token=bb63ce9d-95e7-4626-beb2-4c806b886b7d" alt=""><figcaption></figcaption></figure>

このMySQL Dockerfileでは、**ENTRYPOINT**は`["docker-entrypoint.sh"]`で、**CMD**は`["mysqld"]`です。つまり、**ENTRYPOINT**は**CMD**の先頭に追加されるため、コンテナの起動時に`docker-entrypoint.sh mysqld`が実行されます。

#### `docker-compose.yml`

docker-composeは2つのサービスを使用します。

**init**サービスは、`keeper/keeper-secrets-manager-cli` Dockerイメージボリュームをロードします。このイメージは起動して終了しますが、終了後もボリュームには引き続きアクセスできます。

**main**サービスは、**init**サービスの後に実行されます。これは、docker-composeの`depends_on`ディレクティブを使用して実行します。このサービスには、KSM CLI `exec`コマンドによって置き換えられる、[表記法](https://docs.keeper.io/jp/keeperpam/secrets-manager/about/keeper-notation)を使用した環境変数が含まれており、KSM CLIに必要なBase64でエンコードされた設定も含まれています。**MYSQL\_**&#x74B0;境変数は、データベースをプロビジョニングするために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>。
