DevOps

Jenkins와 AWS ECR을 사용한 Docker 배포 [4] - 배포스크립트 작성

nineDeveloper 2021. 7. 11.
728x90

Jenkins와 AWS ECR을 사용한 Docker 배포 [1] - AWS ECR Private Repository 생성 및 설정
Jenkins와 AWS ECR을 사용한 Docker 배포 [2] - Jenkins 서버에서 AWS ECR 로그인 하기
Jenkins와 AWS ECR을 사용한 Docker 배포 [3] - Jenkins 설정
Jenkins와 AWS ECR을 사용한 Docker 배포 [4] - 배포스크립트 작성

배포스크립트 작성

아래의 스크립트 내용에 대한 자세한 내용은 생략한다

Jenkins 와 AWS ECR을 사용한 Docker 배포에 대한 이해를 돕기위해 Application 배포 스크립트 내용을 추가하였다

1. Dockerfile 작성

먼저 Dockerfile 을 작성한다 이 Dockerfile 은 Jenkins 에서 Docker Push 를 할때 Docker 이미지를 생성 하는 역할을 한다

# AWS ECR PUSH용 Dockerfile
FROM azul/zulu-openjdk:11

ARG JAR_FILE=build/libs/*.jar
ARG SPRING_PROFILE
#ARG SERVER_IP
#ARG SERVER_PORT

# 언어 설정
RUN apt-get update && apt-get -y install sudo
#apt-get install -y language-pack-ko && \
#RUN locale-gen ko_KR.UTF-8
#RUN update-locale LC_ALL=ko_KR.UTF-8 LANG=ko_KR.UTF-8
ENV LANG ko_KR.UTF-8
ENV LANGUAGE ko_KR.UTF-8
ENV LC_ALL ko_KR.UTF-8
ENV SPRING_PROFILE=${SPRING_PROFILE:-local}
#ENV SERVER_IP=${SERVER_IP:-127.0.0.1}
#ENV SERVER_PORT=${SERVER_PORT:-9001}

# TimeZone 설정
ENV TZ=Asia/Seoul
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN echo "GID = 1000" \
    echo "UID = 1000"

## 유저 및 그룹추가 sudo 추가
RUN groupadd --gid 1000 ubuntu \
    && useradd --uid 1000 --gid 1000 --create-home ubuntu \
    && adduser ubuntu sudo \
    && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

## 유저 설정
USER 1000:1000
## 작업 디렉토리 설정
WORKDIR /home/ubuntu

RUN mkdir tmpfiles files

RUN ls -alt

COPY ${JAR_FILE} app.jar
## app 소유자와 그룹 USER로 변경처리
RUN sudo chown 1000:1000 app.jar

#ENV JAVA_OPTS="-jar app.jar -Duser.timezone=Asia/Seoul --spring.profiles.active=${SPRING_PROFILE} --SERVER_IP=${SERVER_IP}"
# 원활한 설정을 위해 Docker Build 시 Eureka Client IP 셋팅을 패스하고 docker-compose deploy 시 적용되도록 수정
#  -Dserver.port=${SERVER_PORT} 포트 변경
ENV JAVA_OPTS="-jar app.jar -Duser.timezone=Asia/Seoul --spring.profiles.active=${SPRING_PROFILE}"
#ENV JAVA_OPTS="-jar app.jar -Duser.timezone=Asia/Seoul"
RUN echo ${JAVA_OPTS}

## app 구동
CMD java ${JAVA_OPTS}

2. docker-compose.yml 작성

docker-compose.yml 파일은 deploy.sh 에서 환경변수를 받아 AWS ECR 에서 Docker 이미지를 PULL 받고 Docker Container 를 구동하는 역할을 한다

## docker-compose 버전 3버전의 최신버전을 셋팅
version: '3'

services:
  ## 서비스명 docker-compose up -d [서비스명] 으로
  ## 여러 서비스가 있으면 해당 서비스만 구동할 수 있다
  ## 서비스명이 중복되면 오류가 발생하므로 서비스되는 서비스명으로 변경 해야 한다
  ## SERVICE 명(jar 파일 이름 앞자리와 동일해야함, docker-compose '서비스명-profile'과 같아야함 ex - service-dev)
  test-apis:
    ## 빌드시 생성되는 이미지명과 태그명을 auto_apply.sh 로부터 전달 받아서 지정한다
    image: ${IMAGE_NAME}
    ## 컨테이너 명을 auto_apply.sh 로부터 전달 받아서 지정한다
    container_name: "test-apis-${CONTAINER_TYPE}"
    ## 항상 재기동되는 옵션
    # no: 문제가 발생하여 Container가 중지된 경우 재시작 하지 않음 (default)
    # always: 어떠한 문제로 Container가 중지되는 경우 무조건 재시작
    # on-failure: 컨테이너가 오직 에러로 인해 중단 되었을 경우에만 다시 시작시킨다
    # unless-stopped: 우리가 강제적으로 중단 시킨게 아니라면 항상 컨테이너를 다시 시작 시킨다
    #restart: always
    ## HOST 포트와 컨테이너 포트를 auto_apply.sh 로부터 전달 받아서 지정한다
    ports:
      - ${HOST_PORT}:${HOST_PORT}
    ## 컨테이너만 공개하는 포트
    expose:
      - ${HOST_PORT}
    networks:
      - msa-network
    user: 1000:1000
    ## Docker 컨테이너와 HOST 디렉토리를 맵핑
    volumes:
      - ./logs:/home/ubuntu/logs
      - /etc/localtime:/etc/localtime:ro
    ## 한국 시간 설정
    environment:
      TZ: 'Asia/Seoul'
      COMPOSE_PROJECT_NAME: 'test-apis'
      ZONE: '${ZONE}'
      HOST_PORT: '${HOST_PORT}'
      SERVER_IP: '${SERVER_IP}'
      PUBLIC_SERVER_IP: '${PUBLIC_SERVER_IP}'
      EUREKA_SERVER1: '${EUREKA_SERVER1}'
      EUREKA_SERVER2: '${EUREKA_SERVER2}'
networks:
  msa-network:
    external: true

3. deploy.sh 작성

Jenkins 에서 환경변수를 받아서 스크립트를 수행하고 환경변수를 이용해 BLUE/GREEN 배포를 하도록 구성되어 있다

#!/bin/bash

# 처리할 PROFILE
PROFILE=${PROFILE:-dev}
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] PROFILE=${PROFILE}" | tee deploy.log

EUREKA_SERVER1=${EUREKA_SERVER1:-10.0.0.1}
EUREKA_SERVER2=${EUREKA_SERVER2:-10.0.0.2}

export EUREKA_SERVER1
export EUREKA_SERVER2

AWSCLI_INSTALL=$(aws --version | grep aws-cli | wc -l)

# 만약 AWS CLI2가 설치되지 않았다면
if [ $AWSCLI_INSTALL -ne 1 ];then
  echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] AWS CLI2 설치" | tee -a deploy.log
  # AWS CLI2 설치
  sudo apt update && \
  sudo apt-get install unzip -y && \
  curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
  sudo unzip awscliv2.zip && \
  sudo ./aws/install

  # AWS Configure 셋팅 및 로그인
  aws configure set aws_access_key_id AWS_ACCESS_KEY_ID && \
  aws configure set aws_secret_access_key AWS_SECRET_ACCESS_KEY && \
  aws configure set region ap-northeast-2 && \
  aws configure set output json
fi

echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] AWS ECR Private docker login" | tee -a deploy.log
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 6XXXXXXXXXX0.dkr.ecr.ap-northeast-2.amazonaws.com

DELAY_TIME=${DELAY_TIME:-30}
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] DELAY_TIME=${DELAY_TIME}" | tee -a deploy.log

DOCKER_COMPOSE_FILENAME=docker-compose

export DOCKER_APP_NAME=${1:-product-apis}
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] DOCKER_APP_NAME=${DOCKER_APP_NAME}" | tee -a deploy.log

IMAGE_NAME="6XXXXXXXXXX0.dkr.ecr.ap-northeast-2.amazonaws.com/test/${DOCKER_APP_NAME}"

if [ "${PROFILE}" != "prod" ]; then
  IMAGE_NAME="${IMAGE_NAME}-${PROFILE}"
fi
export IMAGE_NAME
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] IMAGE_NAME=${IMAGE_NAME}" | tee -a deploy.log

if [ "${PROFILE}" == "local" ];then
  echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] 맥북 로컬IP 조회" | tee -a deploy.log
  # 맥북 로컬IP 셋팅
  PUBLIC_SERVER_IP=$(ipconfig getifaddr en0)
  SERVER_IP=$(ipconfig getifaddr en0)
else
  echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] 인스턴스 공인IP 조회" | tee -a deploy.log
  ## 공인IP
  PUBLIC_SERVER_IP=$(curl ifconfig.me)
  NET_TOOLS=$(dpkg -l | grep net-tools | awk '{print $2}')
  if [ -z "${NET_TOOLS}" ];then
    sudo apt install net-tools -y
  fi

  echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] 인스턴스 Private IP 조회" | tee -a deploy.log
  if [ "${PROFILE}" == "dev" ];then
    SERVER_IP=$(ifconfig -a | grep "inet " | grep "netmask 255.255.240.0" | grep "172*"  | awk '{print $2}')
  else
    SERVER_IP=$(ifconfig -a | grep "inet " | grep "netmask 255.255.255.0" | awk '{print $2}')
  fi
fi

export PUBLIC_SERVER_IP
export SERVER_IP

BLUE_PORT=${2:-9005}
GREEN_PORT=${3:-9006}

if [ -z ${DOCKER_APP_NAME} ]; then
 echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] Please Input DOCKER_APP_NAME" | tee -a deploy.log
 echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] EXIT" | tee -a deploy.log
 exit
fi

echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] SERVER_IP=$SERVER_IP" | tee -a deploy.log
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] DOCKER_APP_NAME=$DOCKER_APP_NAME" | tee -a deploy.log

EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --format "{{.ID}}")
EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --format "{{.ID}}")

echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] docker ps --filter name=${DOCKER_APP_NAME}-blue --format '{{.ID}}'" | tee -a deploy.log
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] EXIST_BLUE=${EXIST_BLUE}" | tee -a deploy.log
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] docker ps --filter name=${DOCKER_APP_NAME}-green --format '{{.ID}}'" | tee -a deploy.log
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] EXIST_GREEN=${EXIST_GREEN}" | tee -a deploy.log

echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] 0. make initialize"
if [ ! -d "logs" ];then
  echo "mkdir logs"
  mkdir "logs"
fi

#EXIST_NETWORK=$(docker network inspect msa-network -f "{{json .Id}}")
EXIST_NETWORK=$(docker network ls | grep msa-network)

# 구동중인 컨테이너가 없으면 UP
if [ -z "$EXIST_NETWORK" ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-0] docker network create msa-network" | tee -a deploy.log
    docker network create msa-network | tee -a deploy.log
fi

# 구동중인 컨테이너가 없으면 UP
if [ -z "$EXIST_BLUE" ]; then
    # BLUE 컨테이너를 구동하기 위한 변수 설정
    export HOST_PORT=${BLUE_PORT}
    export CONTAINER_TYPE=blue

    # BLUE 컨테이너 UP
    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] BLUE UP PROCESS.." | tee -a deploy.log

    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml pull ${DOCKER_APP_NAME}" | tee -a deploy.log
    docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml pull ${DOCKER_APP_NAME} > /dev/null 2>&1

    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml up -d --force-recreate --build ${DOCKER_APP_NAME}" | tee -a deploy.log
    docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml up -d --force-recreate --build ${DOCKER_APP_NAME} | tee -a deploy.log

    # BLUE 컨테이너가 구동되기까지 30초정도 대기
    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] BLUE DETECT ${DELAY_TIME}S WAITING.."
    sleep ${DELAY_TIME}

    EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --format "{{.ID}}")
    EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --format "{{.ID}}")

    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] EXIST_BLUE = $EXIST_BLUE, EXIST_GREEN = $EXIST_GREEN" | tee -a deploy.log
    # BLUE 컨테이너 구동이 확인되고 만약 블루/그린 두개의 컨테이너가 구동중이라면 30초 후에 GREEN DOWN
    if [ "$EXIST_BLUE" ] && [ "$EXIST_GREEN" ]; then
        # GREEN 컨테이너를 중지하기 위한 변수 설정
        export HOST_PORT=${GREEN_PORT}
        export CONTAINER_TYPE=green

        # GREEN APPLICATION Graceful Shutdown
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] Green Graceful Shutdown Start..." | tee -a deploy.log
        PID=$(docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml exec ${DOCKER_APP_NAME} ps -ef | grep app.jar | grep -v 'grep' | awk '{print $2}')

        if [ -z "$PID" ]; then
          echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] PID Empty=${PID}" | tee -a deploy.log
          echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] EXIT" | tee -a deploy.log
          exit
        fi

        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] SpringBoot Application PID=${PID}" | tee -a deploy.log

        # GREEN APPLICATION 정상종료 시그널 전송
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml exec sample-apis kill -15 ${PID}" | tee -a deploy.log
        docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml exec ${DOCKER_APP_NAME} kill -15 ${PID} | tee -a deploy.log

        # GREEN APPLICATION 로그 출력 컨테이너 종료 시점을 잡기 위해 출력
        # APPLICATION이 종료되면 로그가 닫히고 다음으로 넘어감
#        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml logs -f -t --tail='all' ${DOCKER_APP_NAME}" | tee -a deploy.log
#        docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml logs -f -t --tail="all" ${DOCKER_APP_NAME} | tee -a deploy.log

        # GREEN APPLICATION 종료될때까지 30초 대기 후 종료절차 시작
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] ${DOCKER_APP_NAME}-${CONTAINER_TYPE} 종료 ${DELAY_TIME}초 대기" | tee -a deploy.log
        sleep ${DELAY_TIME}

        # GREEN 컨테이너 DOWN
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-3] GREEN DOWN PROCESS.." | tee -a deploy.log

        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-3] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml down" | tee -a deploy.log
        docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml down | tee -a deploy.log
    fi
# 구동중인 컨테이너가 있으면 down
else
    # GREEN 컨테이너를 구동하기 위한 변수 설정
    export HOST_PORT=${GREEN_PORT}
    export CONTAINER_TYPE=green

    # GREEN 컨테이너 UP
    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] GREEN UP PROCESS.." | tee -a deploy.log

    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml pull ${DOCKER_APP_NAME}" | tee -a deploy.log
    docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml pull ${DOCKER_APP_NAME} > /dev/null 2>&1

    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml up -d --force-recreate --build ${DOCKER_APP_NAME}" | tee -a deploy.log
    docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml up -d --force-recreate --build ${DOCKER_APP_NAME} | tee -a deploy.log

    # GREEN 컨테이너가 구동되기까지 30초정도 대기
    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] GREEN DETECT ${DELAY_TIME}S WAITING.." | tee -a deploy.log
    sleep ${DELAY_TIME}

    EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --format "{{.ID}}")
    EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --format "{{.ID}}")

    echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-1] EXIST_BLUE = $EXIST_BLUE, EXIST_GREEN = $EXIST_GREEN" | tee -a deploy.log

    # GREEN 컨테이너 구동이 확인되고 만약 블루/그린 두개의 컨테이너가 구동중이라면 30초 후에 BLUE DOWN
    if [ "$EXIST_GREEN" ] && [ "$EXIST_BLUE" ]; then
        # BLUE 컨테이너를 구동하기 위한 변수 설정
        export HOST_PORT=${BLUE_PORT}
        export CONTAINER_TYPE=blue

        # BLUE APPLICATION Graceful Shutdown
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] Blue Graceful Shutdown Start..." | tee -a deploy.log
        PID=$(docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml exec ${DOCKER_APP_NAME} ps -ef | grep app.jar | grep -v 'grep' | awk '{print $2}')

        if [ -z "$PID" ]; then
          echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] PID Empty=${PID}" | tee -a deploy.log
          echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] EXIT" | tee -a deploy.log
          exit
        fi

        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] SpringBoot Application PID=${PID}" | tee -a deploy.log

        # BLUE APPLICATION 정상종료 시그널 전송
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml exec ${DOCKER_APP_NAME} kill -15 ${PID}" | tee -a deploy.log
        docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml exec ${DOCKER_APP_NAME} kill -15 ${PID} | tee -a deploy.log

        # BLUE APPLICATION 로그 출력 컨테이너 종료 시점을 잡기 위해 출력
        # APPLICATION이 종료되면 로그가 닫히고 다음으로 넘어감
#        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml logs -f -t --tail='all' ${DOCKER_APP_NAME}" | tee -a deploy.log
#        docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml logs -f -t --tail="all" ${DOCKER_APP_NAME} | tee -a deploy.log
        #sleep ${DELAY_TIME}

        # BLUE APPLICATION 종료될때까지 30초 대기 후 종료절차 시작
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-2] ${DOCKER_APP_NAME}-${CONTAINER_TYPE} 종료 ${DELAY_TIME}초 대기" | tee -a deploy.log
        sleep ${DELAY_TIME}

        # BLUE 컨테이너 DOWN
        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-3] BLUE DOWN PROCESS.." | tee -a deploy.log

        echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-3] docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml down" | tee -a deploy.log
        docker-compose -p ${DOCKER_APP_NAME}-${CONTAINER_TYPE} -f ./${DOCKER_COMPOSE_FILENAME}.yml down | tee -a deploy.log
    fi
fi

## 이름이 없거나 태그가 없는 사용되지 않는 모든 이미지 삭제
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-4] docker image prune -a -f" | tee -a deploy.log
docker image prune -a -f | tee -a deploy.log # > /dev/null 2>&1
## 중지된 모든 컨테이너 삭제
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-4] docker container prune -f" | tee -a deploy.log
docker container prune -f | tee -a deploy.log # > /dev/null 2>&1
## 중지된 모든 네트워크 삭제
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-4] docker network prune -f" | tee -a deploy.log
docker network prune -f | tee -a deploy.log # > /dev/null 2>&1
## 중지된 모든 볼륨 삭제
echo "[$(date '+%Y-%m-%d %H:%M:%S')][STEP-4] docker volume prune -f" | tee -a deploy.log
docker volume prune -f | tee -a deploy.log # > /dev/null 2>&1
728x90

댓글

💲 추천 글