1377
nom
2023/07/14
0
最近,皆が使うグラフ描画ツールを統一したほうがいいんじゃないかという話になり,Python + matplotlib を使おうとしています.そこで,実行環境も揃えるために Docker + シェルスクリプトでコマンドを作ってみました.
matplot というコマンドです.これで,環境によってグラフの凡例に日本語が出ないとかいうことがなくなりそうです.
→ nomlab/tools - GitHub
短かいので,同じものを末尾にも丸ごと載せておきます.
このスクリプトのウリは,Dockerfile も内蔵しているところです.これまで Docker + シェルスクリプトで CLI を作ることはあったのですが,対応する Dockerfile と共に管理するのが面倒でした.
シェルスクリプト中にヒアドキュメントとして入れておいて,なおかつ Dockerfile 部分の書換後や初回実行時には,自動で docker build が走ります.
中身は単に matplotlib 他をあらかじめインストールした Python なので,
matplot ./your-plot-script.py という感じで使えます (pwd をマウントしてます).引数なしだと bash が起動します.
もう1つのウリは,実行する UID をホストとゲストで (極力) そろえているところです.作ったファイルが root 所有にならないようにしています.
よかったら,使ってみて PR を下さい.
#!/bin/bash
set -e
HOST_USER_ID=$(id -u)
HOST_USER_NAME=$(id -un)
IMG_NAME="matplot"
IMG_TAG="latest"
IMG_NAME_TAG="${IMG_NAME}:${IMG_TAG}"
function dockerfile() {
cat <<EOF
FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y sudo vim python3 python3-pip
RUN apt-get install -y fonts-ipaexfont
RUN pip3 install pandas matplotlib scipy
RUN useradd -m -s /bin/bash -u $HOST_USER_ID $HOST_USER_NAME
RUN usermod -aG sudo $HOST_USER_NAME
RUN sed -i 's/^%sudo.*$/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/' /etc/sudoers
RUN mkdir /home/$HOST_USER_NAME/work
RUN touch /home/$HOST_USER_NAME/.sudo_as_admin_successful
RUN chown -R ${HOST_USER_NAME}:${HOST_USER_NAME} /home/$HOST_USER_NAME
RUN sed -i "s/^#font\.family.*/font.family: IPAexGothic/g" /usr/local/lib/python*/dist-packages/matplotlib/mpl-data/matplotlibrc
USER $HOST_USER_NAME
WORKDIR /home/$HOST_USER_NAME/work
CMD ["bash"]
EOF
}
function dockerfile_signature() {
dockerfile | md5sum | sed 's/ .*//'
}
function img_signature() {
local name_and_tag="$1"
docker inspect "$name_and_tag" \
--format='{{.Config.Labels.dockerfile_signature}}' 2>/dev/null
}
function img_is_uptodate() {
local name_and_tag="$1"
test "$(dockerfile_signature)" = "$(img_signature "$name_and_tag")"
}
# Build Docker image locally.
# Usage: build_img "matplot:latest"
#
function build_img() {
local name_and_tag="$1"
dockerfile | \
docker build \
--label dockerfile_signature=$(dockerfile_signature) \
-t "$name_and_tag" -f - .
}
################################################################
## main
if ! img_is_uptodate "$IMG_NAME_TAG"; then
build_img "${IMG_NAME_TAG}"
fi
if [ $# -eq 0 ]; then
command="bash"
else
command="python3"
fi
docker run -t -i --rm -v .:/home/$HOST_USER_NAME/work \
--name "$IMG_NAME" "$IMG_NAME_TAG" "$command" "$@"
No comment