ようへいの日々精進XP

よかろうもん

続 Docker をソースコードからビルドする + α

前回の続き。

tl;dr

「Logging driver for CloudWatch Logs の動作確認」にて環境変数に設定した Credential な情報が読まれないという件で GitHub の issue に質問をさせて頂いたところ早速返答を頂けたのでメモ。

Failed to initialize logging driver(Logging Driver Cloudwatch Logs) · Issue #16551 · docker/docker · GitHub

samuelkarp さん、本当に有難うございました。


結論

雑に意訳すると

頂いた返答を雑に意訳すると...

Credential な情報は Docker デーモンでは無く Docker クライアントに定義する必要がありますが、Ubuntu 上の sysvinit script を利用している場合には /etc/default/docker に Credential な情報を設定してみてください。尚、適切な権限が設定されたインスタンスプロファイルが適用された EC2 インスタンスであればこの操作が不要です。

とのこと。なるほど、なるほど。

ちゃんと...

Docker とかクラウドとか言う前にサービスの起動方法等について基礎から学ぶ必要があると思った...。お恥ずかしい。

とは言え、一応、試す

/etc/default/docker に credential な情報を設定する

$ sudo sh -c 'cat << EOT >>/etc/default/docker
export AWS_REGION=ap-northeast-1
export AWS_ACCESS_KEY_ID=AKxxxxxxxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EOT
'

Docker デーモンを再起動

$ sudo service docker restart

docker run する

$ docker -D run --rm -it \
  --log-driver=awslogs \
  --log-opt awslogs-region=ap-northeast-1 \
  --log-opt awslogs-group=docker-log \
  --log-opt awslogs-stream=hello-world hello-world

Hello from Docker.
This message shows that your installation appears to be working correctly.

(snip)

DEBU[0000] [hijack] End of stdout
DEBU[0000] End of CmdRun(), Waiting for hijack to finish.

CloudWatch Logs のログストリームを確認する

$ aws logs get-log-events \
  --log-group-name docker-log \
  --log-stream-name hello-world \
  --limit 3
{
    "nextForwardToken": "f/32188739955785962934789305178557178481590524537864716302",
    "events": [
        {
            "ingestionTime": 1443393017862,
            "timestamp": 1443393019795,
            "message": " https://hub.docker.com"
        },
        {
            "ingestionTime": 1443393017862,
            "timestamp": 1443393019795,
            "message": "For more examples and ideas, visit:"
        },
        {
            "ingestionTime": 1443393017862,
            "timestamp": 1443393019795,
            "message": " https://docs.docker.com/userguide/"
        }
    ],
    "nextBackwardToken": "b/32188739955785962934789305178557178481590524537864716300"
}

おお、ログが CloudWatch Logs に記録された。

例えば異なるリージョンの CloudWatch Logs に飛ばしたい場合

# us-east-1 に Log Group を作る
$ aws --region us-east-1 logs create-log-group \
 --log-group-name docker-log

# --log-opt awslogs-region=us-east-1 を指定して docker run
$ docker -D run --rm -it \
  --log-driver=awslogs \
  --log-opt awslogs-region=us-east-1 \
  --log-opt awslogs-group=docker-log \
  --log-opt awslogs-stream=hello-world hello-world

Hello from Docker.
This message shows that your installation appears to be working correctly.

(snip)

DEBU[0000] [hijack] End of stdout
DEBU[0000] End of CmdRun(), Waiting for hijack to finish.

$ aws --region us-east-1 logs get-log-events \
 --log-group-name docker-log \
 --log-stream-name hello-world \
 --limit 3
{                                                                                                                      
    "nextForwardToken": "f/32188905348816712933185230881410086971800679435425087508",                                  
    "events": [                                                                                                        
        {                                                                                                              
            "ingestionTime": 1443400434387,                                                                            
            "timestamp": 1443400436274,                                                                                
            "message": " https://hub.docker.com\r"                                                                     
        },                                                                                                             
        {                                                                                                              
            "ingestionTime": 1443400434387,                                                                            
            "timestamp": 1443400436274,                                                                                
            "message": "\r"                                                                                            
        },                                                                                                             
        {                                                                                                              
            "ingestionTime": 1443400434387,                                                                            
            "timestamp": 1443400436275,                                                                                
            "message": "\r"                                                                                            
        }                                                                                                              
    ],                                                                                                                 
    "nextBackwardToken": "b/32188905348794412187986700258268551253528031073919107090"                                  
}                                                                                                                      

メモ

/etc/default/docker に credential な情報を書くことについて

  • セキュリティ上あんまり良くないような気がするが権限を絞るに限る
  • EC2 で使う場合にはインスタンスプロファイルに適切なロールを割り当てるのがベスト

init スクリプトで起動するサービスにて環境変数を渡したい場合

もはや Docker 関係ないけど、以下のような init スクリプトを用意して試してみる。

$ sudo sh -c 'cat << EOT >>/etc/init.d/envtest
#!/bin/bash
### BEGIN INIT INFO
# Provides:          envtest
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6

. /lib/lsb/init-functions
if [ -f /etc/default/envtest ]; then
  . /etc/default/envtest
fi

env | tee /tmp/envtest-$(date +%Y%m%d%H%M%S).log
EOT
'

コマンドライン上で export FOO=baz と実行するのと /etc/default/envtestexport FOO=bar を設定した状態でどちらが env コマンドの出力結果に含まれるか(環境変数として定義されるか)を確認する。

# export FOO=baz
# service envtest
TERM=screen
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
SHLVL=1
_=/usr/bin/env

FOO=baz は含まれていない。

ちなみに /etc/init.d/envtest と実行すると...以下のように FOO=baz が反映されている。

# /etc/init.d/envtest
XDG_SESSION_ID=2
TERM=screen
SHELL=/bin/bash
FOO=baz

(snip)

LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env

なるほど、service コマンドで実行する場合と /etc/init.d/envtest で実行する場合で出力が異なるようだ。この辺りについてこちらの記事が参考になる。

  • /etc/default/envtestexport FOO=bar を設定
# echo "export FOO=bar" > /etc/default/envtest
# cat /etc/default/envtest
export FOO=bar
# service envtest
TERM=screen
FOO=bar
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
SHLVL=1
_=/usr/bin/env

FOO=bar は含まれている。


以上

自分の未熟さで samuelkarp さんには余計な手間を取らせることになってしまったが、とても勉強になった気がする。有難うございましたm(__)m。