Linux環境でのインストールスクリプト確認用にdocker-composeを整備する
開発したプログラムが複数の環境上で動くかどうかの確認をしたいときがある.
例えばUbuntu
, CentOS
はバージョン・ディストリの特徴によって環境が僅かに違うが,新しいOSをインストールした際の設定自動化スクリプトはどんな場所でも動いてほしい.
例えば自分が作成したプログラムのコンパイル・インストールをどんな環境でも動くスクリプト1つ実行する形にまで仕上げたいとき
しかしこれを全環境の仮想マシンを用意してチェックしていくのは面倒だ.
というわけでdocker-compose
を使って一斉に各ディストリで動くかどうかをチェックする環境を作った話.
やりたかったこと
最初に書いた理由も再掲.
- 作ったプログラムが各ディストリ・バージョン上で動くかどうか簡単に確かめたい
- 開発環境で動くようになったがまっさらな環境で動くのか確認したい
- 上記を一斉に行いたい
とうわけでコンパイル・インストールを確認する環境を作り,自分の環境構築用スクリプトが動くかどうかを確かめた.
何を使って実現するか
他の人がどうやっているのか知らないがいくつか案を練った.
- Virtualboxを複数立てて(
vagrant
を使う?)SSHで同時接続 - コンテナ(
docker-compose
,Kubernetes
)を使う - ラズパイをたくさん買ってPCを複数接続できるキーボードを用意して頑張る(ド鬼畜)
3.は財布的・手間的にない.1.は理想的だが手間がかかる.
2.が現実的かな.
docker-compose
とKubernetes
を比較すると後者のほうが大規模の構成ができそうだ.
が,今回の用途だとそこまで複雑な実装は不要そう.
zozoのブログが非常に刺激になり,現実的な実装を思いつけた.
考えたアーキテクチャ
考慮した結果こうなった.
開発者は端末から最初コマンドを実行すればあとはコンテナを立ち上げ,各コンテナ内での標準入出力をログとしてホスト上に保存する.
ファイル構成はこんな感じ.
|--dists # 各ディストリ設定を置く | |--ubuntu | | |--Dockerfile | | |--personal-settings.yml |--docker-compose.yml # 共通設定 |--.env # 環境変数 |--logs # 各コンテナからのログの保存先 | |--ubuntu.log # ubuntuコンテナからのログ(dists/???は???.logというファイルを作る) |--run_env_test.sh # テスト実行
コンテナの追加はシンプルにしたかった.
考えた結果,追加はdists
以下にコンテナ用の設定ディレクトリを追加するだけで良いようにした.
$ cp dists/ubuntu dists/centos
とかして,中のファイルをいじれば良い.
各ファイルの中身
dists/<ディストリ>/Dockerfile
例はubuntu
の場合で説明.
FROM ubuntu # 好きなコンテナを指定.他の設定もお好みで追加.
dists/<ディストリ>/personal-settings.yml
ubuntu
の場合.
各コンテナ固有の設定を書く.
ホスト上のディレクトリをマウントして共有している.
command
のところに実行したいコマンドを入力する.
今入力されているのは環境構築用のスクリプト.
最後のsleep
コマンドはエラーが合った時にデバッグするためにbash
を継続させる.
version: "3.7" services: ubuntu: image: ubuntu tty: true container_name: 'ubuntu' environment: APP_ENV: ubuntu volumes: - ./dists/ubuntu/Dockerfile:/mnt/host/Dockerfile:ro - ./dists/ubuntu/personal-settings.yml:/mnt/host/personal-settings.yml:ro - ./logs:/mnt/host/logs command: bash -c 'apt -y update > /mnt/host/logs/ubuntu.log && apt -y install git >> /mnt/host/logs/ubuntu.log && git clone https://github.com/poppycompass/dotfiles >> /mnt/host/logs/ubuntu.log && cd dotfiles >> /mnt/host/logs/ubuntu.log && ./start.sh >> /mnt/host/logs/ubuntu.log && sleep 600' volumes: ubuntu: driver_opts: type: none # 絶対パスで指定する device: /home/user/logs o: bind
.env
環境設定用ファイル.
UBUNTU=ubuntu
run_env_test.sh
テストを実行するために使うスクリプト.
コンテナの完全初期化と実行というシンプルな内容.
#!/bin/sh # installation test for each Linux distributions TOPDIR="dists" COMMON="docker-compose.yml" readonly DEBUG=false if "${DEBUG}"; then DISTS="ubuntu" # 1つずつの環境で実行したいとき else DISTS=`ls ${TOPDIR}` fi # Run your installation process function run () { for dist in ${DISTS} do # sudo docker ps # sudo docker exec -it <hash> bash sudo docker-compose -f ${COMMON} -f ${TOPDIR}/${dist}/personal-settings.yml -p ${dist} up -d done; } # Initialize all docker containers function initialize () { sudo docker stop $(sudo docker ps -aq) sudo docker rm $(sudo docker ps -aq) sudo docker network prune -f sudo docker rmi -f $(sudo docker images --filter dangling=true -qa) sudo docker volume rm $(sudo docker volume ls --filter dangling=true -q) sudo docker rmi -f $(sudo docker images -qa) } # Show help function show_help () { echo "Usage: ./run_env_test.sh [options]" echo "[options]: " echo " run : run your installation process" echo " init: initialize all container" } # Main routines if [ "$1" == "run" ]; then run elif [ "$1" == "init" ]; then initialize else show_help fi
実行
$ ./run_env_test.sh run
これで各コンテナが実行される.
$ tail -f logs/ubuntu.log
とかすればコンテナ内で何が行われているか把握できる.
初期化
コンテナをまっさらな状態にしたいときは
$ ./run_env_test.sh init
評価
やりたかったこと(再掲)
- 作ったプログラムが各ディストリ・バージョン上で動くかどうか簡単に確かめたい
→ 各ディストリ・バージョン環境の簡単な追加,コマンド実行ができるようになった! - 開発環境で動くようになったがまっさらな環境で動くのか確認したい
→ コンテナを初期化することで毎回まっさらな環境で試せるようになった! - 上記を一斉に行いたい
→ 一斉に起動可能!
最初に設定した要件は満たした.
改善が必要なところ
- dockerは基本的にrootのため,user環境での実験作成
→add user
からやるのであれば問題ないか? - プログラムを修正してからの再度実行に手間がかかる(Dockerの初期化・再起動させる必要がある.デバッグ時の細かい試し実行がしにくい)
→ 対策考え中
所感
しばらくはこれで運用しようと思う.
Kubernetes
は勉強中のためこっちのほうが良さそうならまた同じような環境を作ろうと思う.
もっと冴えたやり方を知っている方は是非教えてください.
参考
自動テストの実行環境をDockerでお気軽引っ越し - ZOZO Technologies TECH BLOG
Docker入門(第六回)〜Docker Compose〜 | さくらのナレッジ
複数のDockerコンテナを自動で立ち上げる構成管理ツール「Docker Compose」(Dockerの最新機能を使ってみよう:第7回) | さくらのナレッジ
Dockerfileでうまくマウントできないのでdocker-compose.yml使ってマウントする(o*。_。)o - Qiita
Docker Composeのトップレベルvolumesでホストのディレクトリをマウントする - ニューなんとなく書くブログ