LoginSignup
2
1

More than 5 years have passed since last update.

運用ツールとして Docker を使う

Posted at

こんにちは.

皆さんは,Docker を使ってどんなことをしていますか?
開発環境の構築,おうちサーバで遊ぶ,本番環境でアプリをバリバリ動かす...etc
今回,「使ってほしいコマンドラインツールを配布する」という目的で Docker を使ってみました.

背景

今じぶんが働いているところでは,開発環境とプロダクション環境どちらも GCP + Kubernetes (GKE) で動作しています.
開発環境においては,サーバサイドエンジニアは

  1. ローカルの Docker を用いて Image を Build して,
  2. Google Container Registry にアップロードして,
  3. kubernetes-helm を用いてデプロイする というサイクルを回しています.

一連の動作は,スクリプトでラップすることで,クラウドインフラに明るくない開発者でも安全に開発をすることを可能としています.いわゆるデプロイスクリプトですね.

このデプロイスクリプト,内部でいくつものコマンドを必要とします.

  • gcloud
  • kubectl
  • helm
  • stern
  • etc

特に GCP の CLI である gcloud や,Kubernetes の CLI である kubectl などは,
バージョンによる差分や破壊的変更が多く,できればインフラ管理者が一括で管理したい代物です.

これらを Docker Image にまとめて配布することにより,バージョン差異を無くすことができるのではないか?と考えました.

試してみた

以下が試してみたリポジトリになります.
https://github.com/takutakahashi/deploy-tools

dockerhub にも takutakahashi/deploy-tools としてイメージを上げてあります.

動作原理

ファイルの全体像を図解したものが以下の絵です.
pic1.png

  1. エンジニアは,ローカルにあるコマンドを実行します.
  2. ローカルのコマンドは,リポジトリ上のexec_cmdを経由して実行されます.
  3. コマンドは,各種コマンドが実装され,コンフィグフォルダをマウントしたコンテナ上で実行されます.

コンフィグファイルをマウントすることにより,
gcloud のログイン情報や .kube/config など,各種APIにアクセスするための情報を永続化することが可能です.

.deploy/bin/exec_cmd の中身

中でコンテナを起動し(すでにある場合は失敗させ),exec でコマンドを実行します.
コンテナ自体は sleep を無限ループで実行させ,起動した状態を維持させます.
run を無限に実行しているとゴミが溜まるのと,
処理待ち時間が許容できなかったので exec させています.

==> .deploy/bin/exec_cmd <==
#!/bin/bash
docker run --name $APPLICATION -itd \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v $PROJECT_ROOT/.direnv:/root/.config \
  -v $PROJECT_ROOT/.direnv/kube:/root/.kube \
  -v $PROJECT_ROOT/.direnv/helm:/root/.helm \
  -v $PROJECT_ROOT/.direnv/docker:/root/.docker \
  $ADDITIONAL_OPTS \
  $IMAGE 1>/dev/null 2>/dev/null
docker exec -it $APPLICATION $@

.deploy/bin/[cmd] の中身

各種コマンドのフリをするシェルスクリプトになっています.
中身はシンプルに,実行されたコマンド名とオプションをそのまま exec_cmd の引数に与えるだけです.

% tail .deploy/bin/*
==> .deploy/bin/gcloud <==
#!/bin/bash

exec_cmd `basename $0` $@

==> .deploy/bin/helm <==
#!/bin/bash

exec_cmd `basename $0` $@

==> .deploy/bin/kube-prompt <==
#!/bin/bash

exec_cmd `basename $0` $@

==> .deploy/bin/kubectl <==
#!/bin/bash

exec_cmd `basename $0` $@

==> .deploy/bin/stern <==
#!/bin/bash

exec_cmd `basename $0` $@

プロジェクトに適用する

実際に開発しているアプリケーションリポジトリに適用してみます.
python + bottle で開発しているアプリケーションを想定します.
README.md に記載のコマンドを実行すると,スクリプトは以下のディレクトリ構造を構築します.

$tree .
.
├── .deploy
│   ├── Dockerfile
│   ├── bin
│   │   ├── exec_cmd
│   │   ├── gcloud
│   │   ├── helm
│   │   ├── kube-prompt
│   │   ├── kubectl
│   │   └── stern
│   ├── init_project.sh
│   └── start.sh
├── .envrc
├── app.py
└── requirements.txt

初期構築スクリプトが行う処理は以下となります.

  • .deploy という名称で,deploy-tools を git submodule として追加します.
  • .envrc の中身をプロジェクトルートの同ファイルに追記します.
    • .envrc は,direnv コマンドの env ファイルです.この仕組は direnv に依存します.
export PROJECT_ROOT=$PWD #プロジェクトルートのパス
export IMAGE="takutakahashi/deploy-tools:latest" # docker container の image
export PATH=$PWD/.deploy/bin:$PATH # 上図 ① のコマンドパス
export APPLICATION=k8s-ingress-exporter # アプリケーション名 (コンテナ名に使用)
  • 各種コマンドが .deploy/bin/[cmd] へと置き換わります.

実際やってみてどうだったか?

この方式を実用した際に気づいたメリット・デメリットはいくつかありました.

○ プロジェクトごとに認証情報を分離できる

各種認証情報はプロジェクトルート内部に格納され,別プロジェクトの認証情報と分離されます.
プロジェクトAのクラスタに間違えてプロジェクトBをデプロイした!といったことを原理的に防ぐことができます.

○ 初期構築がほぼゼロ & 構築手順のゆらぎゼロ

新メンバーがジョインした際に設定することは,docker と direnv をインストールすることのみです.
各種コマンドのインストール方法の違いによるトラブルシュートの煩雑さから開放されます.

✗ shell 補完が効かない

kubectl completion で設定した補完が効きません.
対応のために kube-prompt を同梱しましたが,人によっては作業に影響がありそうです...

まとめ

「環境の配布」という観点で,Docker を利用することはとても有用だと思いました.
それは,開発環境,オペレーション環境,様々な環境に適用できると思いました.
ぜひ使ってみてください.

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1