ようへいの日々精進XP

よかろうもん

ギョームで使うシェルスクリプトを社内に配布する方法を検討した

tl;dr

  • AWS CLI と Docker コマンドを駆使した社内ツール (Bash スクリプト) を社内メンバーが利用出来るように配布する方法を考えてみた
  • 尚, 記事内のコード等については, サンプルスクリプト以外については, あくまでも妄想で書いたコードである為, 実際に動くかどうかは検証していない (すいません)

シェルスクリプトサンプル

下図のように docker build して, ECR に docker login からのコンテナイメージを push するスクリプト.

f:id:inokara:20190113204305g:plain

スクリプト自体は, 以下のリポジトリに登録済み. 本記事内では tool-a という名前で随所に登場する予定.

github.com

配布パターン (1) 〜 Amazon S3 に設置して配布する 〜

S3 バケットの設定

  • Web Site Hosting を有効にする
    • AWS CLI がセットアップされていない環境も考慮して, curlwget だけで始められるようにする
    • バケットポリシーで許可された拠点 (社内の拠点 IP) からのみアクセスを許可するようにする
  • スクリプト自体は 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] スクリプトをインストールしました."

実際の配布からスクリプトの実行までの流れ

f:id:inokara:20190113205238g:plain

いい感じ.

配布パターン (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

実際の配布からスクリプトの実行までの流れ

f:id:inokara:20190113205757g:plain

いい感じ.

以上

社内のような狭い範囲で共用するスクリプトをどのように配布すれば良いのか考察してみた. シェルスクリプトだけではなく, Golang で書かれたワンバイナリのツールでも同じような感じで配布出来ると考えている.

Amazon S3 がシンプルで良い感じだけど, Docker イメージとして配布する方が実行する環境を汚すことなく, 環境に依存しない実行環境を提供することが出来るような気がする.

適材適所で使い分けられればなあと考えている.