tl;dr
- AWS CLI と Docker コマンドを駆使した社内ツール (Bash スクリプト) を社内メンバーが利用出来るように配布する方法を考えてみた
- 尚, 記事内のコード等については, サンプルスクリプト以外については, あくまでも妄想で書いたコードである為, 実際に動くかどうかは検証していない (すいません)
シェルスクリプトサンプル
下図のように docker build して, ECR に docker login からのコンテナイメージを push するスクリプト.
スクリプト自体は, 以下のリポジトリに登録済み. 本記事内では tool-a という名前で随所に登場する予定.
配布パターン (1) 〜 Amazon S3 に設置して配布する 〜
S3 バケットの設定
- Web Site Hosting を有効にする
- スクリプト自体は Github で管理するので, バケット自体は低冗長化ストレージでちょっとでもコスト削減
- 必要に応じて, アクセスログを取得するような設定にしておきたいところ
ちなみに, 階層構成は以下のような感じを想定.
$ tree oreno-company-tools.s3-website-ap-northeast-1.amazonaws.com oreno-company-tools.s3-website-ap-northeast-1.amazonaws.com ├── tool-a │ ├── script.sh │ └── setup.sh └── tool-b ├── script.sh └── setup.sh 2 directories, 4 files
セットアップシェルスクリプト
以下のようにコマンド一発でセットアップが済ませられるようにセットアップ用のシェルスクリプトを用意する.
curl -s https://oreno-company-tools.s3-website-ap-northeast-1.amazonaws.com/tool-a/setup.sh | bash
setup.sh は実際にインストールされる, tool-a や tool-b のスクリプトが動作する為に必要なツールがインストールされているかチェックするように仕込んでおくと良さそう. 尚, tool-a の場合, AWS CLI や Docker コマンド等の所在がチェックされることになる. 以下のような感じ.
# S3 のエンドポイント URL を指定 S3_URL=s3-ap-northeast-1.amazonaws.com/oreno-company-tools # ツール名 TOOL_NAME=tool-a # 画面出力用の関数 function incho() { printf "\e[34m$1\e[m\n" } function wacho() { printf "\e[33m$1\e[m\n" } # AWS CLI や docker がインストールされていることをチェック for cmd in aws docker do which ${cmd} > /dev/null 2>&1 if [ ! $? -eq 0 ];then wacho "[warn] ${cmd} がインストールされていません. ${cmd} をインストールしてから, 改めてお試し下さい." exit 1 fi done incho "[info] 依存するツールがインストールされていることをチェックしました." # スクリプト本体のインストール if [ -d ${HOME}/bin ];then curl https://${S3_URL}/${TOOL_NAME}/script.sh --output ${HOME}/bin/${TOOL_NAME} && chmod +x ${HOME}/bin/${TOOL_NAME} else wacho "[warn] ${HOME}/bin が存在していません. ${HOME}/bin を作成してから, 改めてお試し下さい." exit 1 fi incho "[info] スクリプトをインストールしました."
実際の配布からスクリプトの実行までの流れ
いい感じ.
配布パターン (2) 〜 Docker コンテナで配布する 〜
おっ, S3 よりもモダンな感じ
配布したいスクリプトや依存するツールをコンテナに封じ込めることで, 手元の端末の環境をきれいな状態に保つことが出来るし, なによりも Docker を使うことで OS 環境に依存しない実行環境が手に入ってモダンな感じだぜ.
以下のように, docker コマンドまたは docker-compose コマンド経由 (docker-compose.yml を用意する必要がある) で, 目的とするスクリプトを実行出来る.
# docker コマンドで実行する場合 docker run -t -i \ -v=/var/run/docker.sock:/var/run/docker.sock \ -v=$(pwd):/work \ -v=${HOME}/.aws:/root/.aws \ -w=/work \ oreno-company-tools/tool-a:latest \ tool-a /work/config.yml # docker-compose コマンドで実行する場合 docker-compose run tool-a config.yml
こうやって見ると, docker-compose の方がシンプルでいい感じ.
コマンドを封じ込める Dockerfile
docker 自体のコンテナを利用する.
FROM docker RUN apk update && apk add bash jq python curl RUN cd /tmp && \ curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip" && \ unzip awscli-bundle.zip && \ ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws ADD script.sh /usr/local/bin/tool-a
Docker コンテナ化することで, 環境を問わず実行出来るようになるのが気持ち良いはず. 以下のように docker run する.
docker run -t -i \ -v=/var/run/docker.sock:/var/run/docker.sock \ -v=$(pwd):/work \ -v=${HOME}/.aws:/root/.aws \ -w=/work \ oreno-company-tools/tool-a:latest \ tool-a /work/config.yml
docker run した場合, かなりボリューミーなコマンドラインオプションとなる為, 以下のように, docker-compose を利用する.
コマンドラインオプションを封じ込める docker-compose.yml
前述の通り, docker run で実行する場合, コマンドラインオプションがボリューミーになる為, コマンドラインオプション自体は docker-compose.yml に封じ込める.
version: '3' services: tool-a: image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/oreno-docker-image/tool-a:latest container_name: tool-a volumes: - /var/run/docker.sock:/var/run/docker.sock - .:/work - ${HOME}/.aws:/root/.aws working_dir: /work entrypoint: /usr/local/bin/tool-a
以下のように実行する. 尚, カレントディレクトリに docker-compose.yml が存在しているとする.
docker-compose run --rm tool-a example/example.yml
実際の配布からスクリプトの実行までの流れ
いい感じ.
以上
社内のような狭い範囲で共用するスクリプトをどのように配布すれば良いのか考察してみた. シェルスクリプトだけではなく, Golang で書かれたワンバイナリのツールでも同じような感じで配布出来ると考えている.
Amazon S3 がシンプルで良い感じだけど, Docker イメージとして配布する方が実行する環境を汚すことなく, 環境に依存しない実行環境を提供することが出来るような気がする.
適材適所で使い分けられればなあと考えている.