요즈음 도커 이미지를 수도 없이 찍어내고 있습니다. 업무 시간 중 대부분을 이미지가 빌드되기를 기다리며, 멍하니 모니터를 바라보는 데 사용하고 있으니까요. 도커 파일이 여러개로 나뉘고 순서대로 빌드해야 하고, 어떤 때는 일부만 빌드하고 어떤 때는 전체를 빌드하거나 할 필요가 생겼습니다. 그리고 빌드된 이미지를 푸시하려면 또 이미지를 하나하나 골라서 푸시하는 과정을 반복하다보니 실수도 잦고 시간도 오래 걸려서 쉘 스크립트를 하나 만들었습니다.
수준 높은 쉘 스크립트는 아니지만, 잘 동작하고 나중에 혹시 필요할 일이 있을까 기록으로 남겨 둡니다.
기능
요구사항은 다음과 같습니다. 간단하죠.
- 도커 이미지를 빌드 할 수 있습니다.
- 도커 이미지는 푸시 할 수 있습니다.
- 빌드 될 대상은 선택할 수 있습니다.
3번 요구사항과 관련하여 빌드 할 이미지는 5가지 입니다. 이미지는 선택할 수 있어야 합니다.
- 공통된 설정과 기본 패키지들을 설치할 base image.
- 사용자로부터 요청을 전달받아 queue에 전달할 receiver
- 사용자의 요청을 보관하는 queue
- 사용자를 순자적으로 처리하는 core
- 주기적으로 무언가를 하는 scheduler
그래서 만든 쉘은 빌드 또는 푸시할 대상을 선택하고, 빌드, 푸시를 하고 때로는 빌드 후 푸시를 하는 일을 사용자의 숫자와 엔터 입력으로 할 수 있게 합니다. 이름은 build.sh로 정했습니다.
코드
build.sh의 코드는 다음과 같습니다. 사용자의 입력을 배열에 저장하고, 배열에 담긴 내용을 확인하여 순차적으로 실행하기 때문에 이미지 빌드 순서가 바뀔일은 없습니다. ( 사실 base 이미지만 먼저 만들어진다면 다른 이미지들의 빌드 순서는 바뀌어도 상관없습니다. )
#!/usr/bin/env bash
JOBS=()
TARGETS=()
BASE_IMAGE="bitlog/base:latest"
RECEIVER_IMAGE="bitlog/receiver"
QUEUE_IMAGE="bitlog/queue"
CORE_IMAGE="bitlog/core"
SCHEDULER_IMAGE="bitlog/scheduler"
TAG=$1
function build_image()
{
if [[ "${TARGETS[@]}" =~ "base" ]]; then
echo "docker build -t $BASE_IMAGE ."
fi
if [[ "${TARGETS[@]}" =~ "receiver" ]]; then
echo "docker build -t $RECEIVER_IMAGE:$TAG ."
fi
if [[ "${TARGETS[@]}" =~ "queue" ]]; then
echo "docker build -t $QUEUE_IMAGE:$TAG ."
fi
if [[ "${TARGETS[@]}" =~ "core" ]]; then
echo "docker build -t $CORE_IMAGE:$TAG ."
fi
if [[ "${TARGETS[@]}" =~ "scheduler" ]]; then
echo "docker build -t $SCHEDULER_IMAGE$TAG ."
fi
}
function push_image()
{
if [[ "${TARGETS[@]}" =~ "base" ]]; then
echo "docker push $BASE_IMAGE "
fi
if [[ "${TARGETS[@]}" =~ "receiver" ]]; then
echo "docker push $RECEIVER_IMAGE:$TAG"
fi
if [[ "${TARGETS[@]}" =~ "queue" ]]; then
echo "docker push $QUEUE_IMAGE:$TAG"
fi
if [[ "${TARGETS[@]}" =~ "core" ]]; then
echo "docker push $CORE_IMAGE:$TAG"
fi
if [[ "${TARGETS[@]}" =~ "scheduler" ]]; then
echo "docker push $SCHEDULER_IMAGE$TAG"
fi
}
function firework()
{
if [[ "${JOBS[@]}" =~ "BUILD" ]]; then
build_image
fi
if [[ "${JOBS[@]}" =~ "PUSH" ]]; then
push_image
fi
}
function select_jobs()
{
echo ""
echo "************ Select jobs ************"
echo ""
PS3='Add items. if finished choose done: '
options=("build only" "push only" "both" "Quit")
select opt in "${options[@]}"
do
case $opt in
"build only")
JOBS=("BUILD")
break
;;
"push only")
JOBS=("PUSH")
break
;;
"both")
JOBS=("BUILD" "PUSH")
break
;;
"Quit")
echo "exit program"
exit
;;
*) echo "invalid option $REPLY";;
esac
done
final_confirm
}
function select_target()
{
echo ""
echo "************ Select Targets ************"
echo ""
PS3='Add items. if finished choose done: '
options=("base" "receiver" "queue" "core" "scheduler" "Done" "Quit")
select opt in "${options[@]}"
do
case $opt in
"base"|"receiver"|"queue"|"core"|"scheduler")
TARGETS+=($opt)
TARGETS=($(printf "%s\n" "${TARGETS[@]}" | sort -u))
;;
"Done")
select_jobs
break
;;
"Quit")
echo "exit program"
exit
;;
*) echo "invalid option $REPLY";;
esac
printf '%s,' "${TARGETS[@]}"
echo ""
done
}
function final_confirm()
{
echo ""
echo "************ Confirm ************"
echo ""
echo "You choose "
printf '%s,' "${TARGETS[@]}"
echo ""
printf '%s,' "${JOBS[@]}"
echo ""
read -p "Are you sure? (y/n)" -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then
echo ""
firework
else
echo "Please Select Again."
JOBS=()
TARGETS=()
select_target
fi
}
select_target
정리
build.sh를 통해서
배열의 출력,
배열에 원소에 특정한 값이 포함되어 있는지 확인,
사용자의 선택을 입력 받는 방법을 알 수 있습니다.
반응형