本シリーズのトップページ |
---|
https://qiita.com/robozushi10/items/eebd8068a0533ba49bea |
はじめに
限られた物理PC の中で、次の Python バージョン
・Python 3.6.8
・Python 3.7.3
・Python 3.8.3
・Python 3.9.4
をインストールしてプログラムを作成することになった.
ただし、物理PC を汚染させるわけにもいかないので Docker を活用した.
(操作しやすいように docker-compose を導入した)
また、物理ホスト側からバッチを使って、極力コンテナに「手動で」ログインせずに
Python コードを実行するようにした.
今後もこの環境構築は頻発すると思うので書き残しておく.
今回は 前回作成した**「ビルドコンテナ」をホスト側から実行するツール** について記す.
なお、今回記すツールは、職場で導入されているツールの挙動を模倣して作成したものであるが、
職場ではもっと保護処理が多く且つ高機能である.
構築後のファイル構成
.
|-- PY-cli-v001.sh ............. 🛑今回作成するファイル (シェルスクリプト)
|-- PV ......................... 永続ボリューム
| `-- py
| `-- app ................ この直下に *.py を配置する
| `-- a.py ........... サンプルコード
|-- assets
| `-- py
| |-- Dockerfile
| `-- requirements.txt ... 導入したい Python パッケージを記述しておく
`-- docker-compose.yml
条件
前回 の手順で実行環境を構築済みであるものとする
手順
1. PY-cli-v001.sh を作成する
下記コードは長々と書いてはあるが、結局のところ次を実行することが目的である.
docker-compose exec py bash -c <コマンド>
で、上記実行時の付加機能として次を追加しているだけである.
・-p
でコンテナ内でのカレントディレクトリを指定できる
・-e
で環境変数を指定できる
・-v
や -V
で実行ログを出す
つまり、コードを読み解くくらいなら作成した方が早いので参考程度に.
#!/bin/bash
# docker-compose.yml で定義したサービス名
SVC=py
# オプション解析
ARGENV=()
while getopts :e:p:c:f:t:vV OPT; do
case $OPT in
e) ARGENV=(${ARGENV[@]} "-e $OPTARG") ;; # 環境変数を「-e」で繋げていく
p) ARGPRJ=$OPTARG ;; # Dockerコンテナ内でのプロジェクトのディレクトリ名
c) CLIMODE="cli"
break ;;
f) ARGDCY=$OPTARG ;; # docker-compose.yml が別名の場合
v) ARGDBGL="1" ;; # 弱デバッグモード
V) ARGDBGL="1"
ARGDBGH="1" ;; # 強デバッグモード
t) ARGMODE="$OPTARG" ;; # init, run, build,...etc
:) echo "Mission arg: -$OPTARG" >&2; exit 1 ;; # オプション引数がない (OPT = :)
*) echo "Unknown option: -$OPTARG" >&2; exit 1 ;; # 不正なオプション (OPT = ?)
esac
done
test "$CLIMODE" = "cli" && {
shift $((OPTIND - 2))
} || {
shift $((OPTIND - 1))
}
# -f は, docker-compose.yml という名称以外の場合に使用する.
test -z "$ARGDCY" && ARGDCY="docker-compose.yml"
test ! -z "$ARGDBGH" && {
echo "[-e] ARGENV => ${ARGENV[@]}"
echo "[-p] ARGPRJ => $ARGPRJ"
echo "[-f] ARGDCY => $ARGDCY"
echo "[-t] ARGMODE => $ARGMODE"
echo "[-c] ARGMODE => $@"
}
# -p で指定できるディレクトリは相対パス表記のみとする. 例: ./usr/src/app か usr/src/app
# 「././PV/py/src/」といったドット連続や絶対パス指定はエラーとする.
case $ARGPRJ in
/*) echo "Error: absolute path not allowed: ARGPRJ => <$ARGPRJ>"
exit 2 ;;
..) echo "Error: could not specify a different layer: ARGPRJ => <$ARGPRJ>"
exit 2 ;;
././*) echo "Error: enter the dot duplicates not allowed: ARGPRJ => <$ARGPRJ>"
exit 2 ;;
./*) DKRPRJ=`echo $ARGPRJ | sed 's%^./%/%g'` ;;
*) DKRPRJ="/$ARGPRJ" ;;
esac
test ! -f $ARGDCY && {
echo 'ERROR: could not found ./docker-compose.yml'
exit 3
}
# ここでの ARGCLI に指定したコマンドが、コンテナ内部で実行される.
case "$ARGMODE" in
*) # -c オプションで指定されたコマンド
test ! -z "$DKRPRJ" && {
ARGCLI="test -d $DKRPRJ && cd $DKRPRJ && $@"
} || {
ARGCLI="$@"
}
;;
esac
# docker-compose exec <環境変数> <SVC> <コマンド> を実行する
docker-compose exec ${ARGENV[@]} $SVC bash -c "
test ! -z \"$ARGDBGL\" && set -x
eval $ARGCLI || {
# eval $ARGCLI に失敗した場合
echo \"[$ARGMODE]:ERROR: eval $ARGCLI\"
test ! -z \"$ARGDBGL\" && set +x
test ! -z \"$ARGDBGH\" && {
echo \"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\"
echo \"Debug Information \"
echo \"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\"
echo \"----------------------------------------------------------------\"
echo \"# pwd\"
echo \"----------------------------------------------------------------\"
pwd
echo \"----------------------------------------------------------------\"
echo \"# env\"
echo \"----------------------------------------------------------------\"
env
}
exit 9
}
test ! -z \"$ARGDBGL\" && set +x
test ! -z \"$ARGDBGH\" && {
echo \"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\"
echo \"Debug Information \"
echo \"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\"
echo \"----------------------------------------------------------------\"
echo \"# pwd\"
echo \"----------------------------------------------------------------\"
pwd
echo \"----------------------------------------------------------------\"
echo \"# env\"
echo \"----------------------------------------------------------------\"
env
}
"
test $? -ne 0 && {
test ! -z "$ARGDBGH" && {
echo "----------------------------------------------------------------"
echo "\$ tree ./PV/$SVC --charset=C -a"
tree ./PV/$SVC --charset=C -a
}
exit 44
}
test ! -z "$ARGDBGH" && {
echo "----------------------------------------------------------------"
echo "\$ tree ./PV/$SVC --charset=C -a"
tree ./PV/$SVC --charset=C -a
}
2. 実行する
通常実行モード
a.py は初回 で作成したコードであり、
単に「Hello Python 0394」と引数を表示するだけのコードである.
$ bash PY-cli-v001.sh -p usr/src/app -c 'python a.py 1 2 3'
Hello Python 0394
1
2
3
もう少し複雑な引数を与えてみる
$ bash PY-cli-v001.sh -p usr/src/app -c 'python a.py \'dateコマンドを実行します\' "`date`"'
Hello Python 0394
dateコマンドを実行します
Wed Aug 4 14:34:10 JST 2021
弱デバッグモード
-v
を付与する
$ bash PY-cli-v001.sh -p usr/src/app -v -c 'python a.py 1 2 3'
+ eval test -d /usr/src/app
++ test -d /usr/src/app
+ cd /usr/src/app
+ python a.py 1 2 3
Hello Python 0394
1
2
3
+ test '!' -z 1
+ set +x
強デバッグモード
-V
を付与する.
$ bash PY-cli-v001.sh -p usr/src/app -V -c 'python a.py 1 2 3'
[-e] ARGENV =>
[-p] ARGPRJ => usr/src/app
[-f] ARGDCY => docker-compose.yml
[-t] ARGMODE =>
[-c] ARGMODE => python a.py 1 2 3
+ eval test -d /usr/src/app
++ test -d /usr/src/app
+ cd /usr/src/app
+ python a.py 1 2 3
Hello Python 0394
1
2
3
+ test '!' -z 1
+ set +x
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Debug Information
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
----------------------------------------------------------------
# pwd
----------------------------------------------------------------
/usr/src/app
----------------------------------------------------------------
# env
----------------------------------------------------------------
PYTHONUNBUFFERED=1
HOSTNAME=6ad7045545ae
PYTHON_VERSION=3.9.4
LANGUAGE=ja_JP.UTF-8
PWD=/usr/src/app
HOME=/root
LANG=ja_JP.UTF-8
GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568
TERM=xterm
SHLVL=1
PYTHON_PIP_VERSION=21.1.1
PYTHONDONTWRITEBYTECODE=1
PYTHON_GET_PIP_SHA256=f499d76e0149a673fb8246d88e116db589afbd291739bd84f2cd9a7bca7b6993
PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/1954f15b3f102ace496a34a013ea76b061535bd2/public/get-pip.py
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
OLDPWD=/usr/src/app
_=/usr/bin/env
----------------------------------------------------------------
$ tree ./PV/py --charset=C -a
./PV/py
`-- app
`-- a.py
1 directory, 1 file